/*!
  @file           vos51k.c
  @author         RaymondR
  @brief          initializations
  @see            

\if EMIT_LICENCE
    ========== licence begin  GPL
    Copyright (c) 2001-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end

\endif
*/




/*
 * INCLUDE FILES
 */
//#include "gos00.h"
#include "gos41.h"
#include "heo00.h"
#include "heo46.h"
#include "geo007_1.h"
#include "gos00k.h"
#include "vsp001c.h"
#include "geo002.h"
#include "heo79.h"
#include "gos003.h"
#include "heo56.h"
#include "heo69.h"
#include "heo92.h"
#include "heo15.h"
#include "RunTime/RTE_KSS.h"
#include "RunTime/RTE_KernelMain.h"
#include "RunTime/RTE_SpawnRestartShutdown.h"
#include "RunTime/RTE_DiagPipe.h"

/*
 *  DEFINES
 */
#define MOD__  "VOS51KC : "
#define MF__   MOD__"UNDEFINED"


// --- VSHUTDOWN --------------------------------------------------------------

typedef enum1                   SHUTDOWN_MODE;

#define SHUTDOWN_KILL           0
#define SHUTDOWN_NORMAL         1

/*
 *  MACROS
 */


/*
 *  LOCAL TYPE AND STRUCT DEFINITIONS
 */


/*
 * EXTERNAL VARIABLES
 */


/*
 *  EXPORTED VARIABLES
 */


/*
 * LOCAL VARIABLES
 */


/*
 * LOCAL FUNCTION PROTOTYPES
 */
static VOID sql51k_start_multiple_tasks ( PTASK_CTRL_REC pFirstMultipleTask,
                                          ULONG          ulNumTasks );

/*
 * ========================== GLOBAL FUNCTIONS ================================
 */

VOID vinitok ( VOID )
  {
  #undef  MF__
  #define MF__ MOD__"vinitok"
  PDLQ_REC                       pRequest;
  PUKT_CTRL_REC                  pTmpUKTCtrl;
  #ifdef DEBUG_RTE
   PTASK_CTRL_REC                pTaskCtrl = THIS_UKT_CTRL->pCTask;
  #endif

  DBGIN_T (pTaskCtrl->ulTaskIndex);


  if ( THIS_UKT_CTRL->pCTask->TaskType != TT_TI )
    {
    MSGD (( ERR_VINITOK_NOT_TIMEOUT ));
    ABORT();
    }

  //
  //
  //  - send startup requests to all non user and server tasks
  //
  //
  pRequest            = RESERVE_FREELIST_ELEM();
  pRequest->ulReqType = REQ_INITOK;
  sql73k_UKT_enqu ( kgs.pAL->pUKT, kgs.pAL, pRequest );

  pRequest            = RESERVE_FREELIST_ELEM();
  pRequest->ulReqType = REQ_INITOK;
  sql73k_UKT_enqu ( kgs.pTW->pUKT, kgs.pTW, pRequest );

  sql51k_start_multiple_tasks ( kgs.pFirstDWTaskCtrl    , XPARAM(ulMaxDataWriter) ) ;
  sql51k_start_multiple_tasks ( kgs.pFirstBackUpTaskCtrl, XPARAM(ulMaxBackupTasks) ) ;
  sql51k_start_multiple_tasks ( kgs.pFirstGCTaskCtrl,     XPARAM(ulMaxGarbageCollector) ) ;


  if ( XPARAM(ulMaxServer) > 0 )
    {

    if ( XPARAM(fDynamicServerTasks) == FALSE )
      /*
       *  send startup requests to all  server tasks
       */
      sql51k_start_multiple_tasks ( kgs.pFirstServerTaskCtrl, XPARAM(ulMaxServer) ) ;

    }

  //
  //
  // - wake up all user kernel threads
  //
  //
  for ( pTmpUKTCtrl =  kgs.pFirstUKTCtrl;
        pTmpUKTCtrl <= kgs.pLastUKTCtrl;
        pTmpUKTCtrl++ )
    {
    if ( pTmpUKTCtrl->ThrdCtrlHeader.hevSem != (HEV) UNDEF )
      sql72k_wake_ukt( pTmpUKTCtrl );
    }


  DBGOUT_T (pTaskCtrl->ulTaskIndex);
  return;
  }

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

VOID vgetuktid ( tsp00_Int4  *id )
  {
  #undef  MF__
  #define MF__ MOD__"vgetuktid"

  *id = (tsp00_Int4)THIS_UKT_CTRL->ulUKTIndex;
  }

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

VOID vgetpid ( PROCESS_ID  *pid )
{
#undef  MF__
#define MF__ MOD__"vgetpid"

    PUKT_CTRL_REC                 pUKT      = THIS_UKT_CTRL;
    if ( !pUKT || !pUKT->pCTask )
    {
        *pid = 0; /* called from other type of thread or not within task */
    }
    else
    {
#ifdef DEBUG_RTE
        PTASK_CTRL_REC                pTaskCtrl = pUKT->pCTask;
#endif
        DBGPAS_T (pTaskCtrl->ulTaskIndex);

        DBG3 (( MF__, "[T:0x%03u] called ", pTaskCtrl->ulTaskIndex ))

        *pid = pUKT->pCTask->ulTaskIndex;
    }
}

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

VOID vmovelock ( PROCESS_ID  pid )
  {
  #undef  MF__
  #define MF__ MOD__"vmovelock"

  DBGPAS_T (pTaskCtrl->ulTaskIndex);

  // set temporary move lock
  //
  #ifdef DEVELOP_CHECKS
   sql74k_temp_move_lock ( THIS_UKT_CTRL->pCTask, 1, true );
  #else
   sql74k_temp_move_lock ( &kgs.pFirstTaskCtrl[pid - 1], 1, true );
  #endif
  }

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

VOID vmoveunlock ( PROCESS_ID  pid )
  {
  #undef  MF__
  #define MF__ MOD__"vmovelock"

  DBGPAS_T (pTaskCtrl->ulTaskIndex);

  // remove temporary move lock
  #ifdef DEVELOP_CHECKS
   sql74k_temp_move_lock ( THIS_UKT_CTRL->pCTask, 1, false );
  #else
   sql74k_temp_move_lock ( &kgs.pFirstTaskCtrl[pid - 1], 1, false );
  #endif
  }

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

VOID vgetfirstuserpid ( PROCESS_ID  *pid )
  {
  #undef  MF__
  #define MF__ MOD__"vgetfirstuserpid"
  #ifdef DEBUG_RTE
   PTASK_CTRL_REC                pTaskCtrl = THIS_UKT_CTRL->pCTask;
  #endif

  DBGPAS_T (pTaskCtrl->ulTaskIndex);

  DBG3 (( MF__, "[T:0x%03u] called ", pTaskCtrl->ulTaskIndex ))

  *pid = kgs.pFirstUserTaskCtrl->ulTaskIndex;
  }

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

VOID vdebug_break ( INT4 i4DebugBreakPosition )
  {
  #undef  MF__
  #define MF__ MOD__"vdebug_break"
  
  if ( i4DebugBreakPosition < 10000 )
    {
    MSGALL (( ERR_WRONG_DEBUG_BREAK_POS, i4DebugBreakPosition, 10000 ));
    DBGOUT;
    return;
    }

  sql51k_debug_break ((ULONG)i4DebugBreakPosition );

  DBGOUT;
  return;
  }

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

VOID vptype ( PROCESS_ID         pid,
              tsp2_process_type  *proc_type )
  {
  #undef  MF__
  #define MF__ MOD__"vptype"
  #ifdef DEVELOP_CHECKS
   PTASK_CTRL_REC                 pTaskCtrl = THIS_UKT_CTRL->pCTask;
  #else
   PTASK_CTRL_REC                 pTaskCtrl = &kgs.pFirstTaskCtrl[pid - 1];
  #endif

  DBGIN_T (pTaskCtrl->ulTaskIndex);

  #ifdef DEVELOP_CHECKS
   if ( (ULONG)pid != pTaskCtrl->ulTaskIndex )
     {
     MSGD (( ERR_VXXXX_WRONG_TASK, "vptype", pid ));
     DBG1 (( MF__, "[T:0x%03u] Wrong pid %u", pTaskCtrl->ulTaskIndex, pid ));
     ABORT();
     }
  #endif

  switch ( pTaskCtrl->TaskType )
    {
    case TT_UT:
        *proc_type = sp2pt_utility;
        break;
    case TT_TI:
        *proc_type = sp2pt_timeout;
        break;
    case TT_US:
        *proc_type = sp2pt_user;
        break;
    case TT_AL:
        *proc_type = sp2pt_log_writer;
        break;
    case TT_TW:
        *proc_type = sp2pt_trace_writer;
        break;
    case TT_SN:
        *proc_type = sp2pt_sender;
        break;
    case TT_RC:
        *proc_type = sp2pt_receiver;
        break;
    case TT_SV:
        *proc_type = sp2pt_server;
        break;
    case TT_DW:
        *proc_type = sp2pt_data_writer;
        break;
    case TT_EV:
        *proc_type = sp2pt_event;
        break;
    case TT_GC:
        *proc_type = sp2pt_garbage_collector;
        break;
    case TT_BUP:
        *proc_type = sp2pt_backup;
        break;
    default:
        MSGALL(( ERR_VPTYPE_WRONG_TASK_TYPE, pTaskCtrl->TaskType ));
        ABORT();
        break;
    }

  DBG3 (( MF__, "[T:0x%03u] *proc_type: %d", pTaskCtrl->ulTaskIndex, *proc_type ))

  DBGOUT_T (pTaskCtrl->ulTaskIndex);
  return;
  }

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

VOID vversion ( tsp00_Version  kernelversion,
                tsp00_Version  lzuversion )

  {
  #undef  MF__
  #define MF__ MOD__"vversion"
  static BOOL         fVersionCalled = FALSE;
  #if defined (_WIN32)
   REG_ENTRY_REC       RegistryEntries[1];
   PATHNAME            szSubKey;
  #endif

  DBGPAS;

  eo46PtoC ( pkss->KernelVersion, kernelversion, sizeof(tsp00_Version) );
  eo46CtoP ( lzuversion, pkss->RTEVersion, sizeof(tsp00_Version) );

  if ((strncmp ( XPARAM(szKernelVersion) + BEG_OF_1ST_VERS_SUBSTR_SP100,
                 pkss->KernelVersion + BEG_OF_1ST_VERS_SUBSTR_SP100,
                 END_OF_1ST_VERS_SUBSTR_SP100 - BEG_OF_1ST_VERS_SUBSTR_SP100  + 1 )) ||
      (strncmp ( XPARAM(szKernelVersion) + BEG_OF_2CND_VERS_SUBSTR_SP100,
                 pkss->KernelVersion + BEG_OF_2CND_VERS_SUBSTR_SP100,
                 END_OF_2CND_VERS_SUBSTR_SP100 - BEG_OF_2CND_VERS_SUBSTR_SP100  + 1 )))
     {
     MSGALL(( ERR_PARAM_AND_KERNEL_INCOMP,
              pkss->KernelVersion,
              XPARAM(szKernelVersion) ))

     ABORT_NO_CRASH_DUMP();
     }
  else if ( fVersionCalled == FALSE )
    {
    fVersionCalled = TRUE;

    MSGD (( INFO_VERSION, pkss->KernelVersion ))
    MSGD (( INFO_VERSION, pkss->RTEVersion ))

    #if defined (_WIN32)
     if ( kgs.fRunningAsNTService == TRUE )
       {
       //
       // --- update the KERNEL-VERSION (KernelVersion) only!!!!
       //     The RTE-Version (Version) is needed for installation checks.
       //
       strcpy ( szSubKey, kgs.szServiceName);
       strcat ( szSubKey, "\\"REG_SK_SERVICE_PARAM );
       RegistryEntries[0].pszValueName = REG_VN_KERNEL_VERSION;
       RegistryEntries[0].pValue       = pkss->KernelVersion;
       RegistryEntries[0].ulValueSize  = (ULONG)strlen(pkss->KernelVersion);
       RegistryEntries[0].ulValueType  = REG_SZ;

       sql50_reg_put_service_values ( NULL, szSubKey, 1, RegistryEntries );
       }
    #endif
    }

  return;
  }

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

VOID  vos ( UINT1 *os )
  {
  #undef  MF__
  #define MF__ MOD__"vos"
  DBGPAS;

  #if defined(_WIN32)
   *os = OS_WIN32;
  #else
   *os = OS_OS2;
  #endif

  return;
  }

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

VOID vinit ( PRTE_COMM_REC   *rte_comm_ptr,
             INT2            len )
  {
  #undef  MF__
  #define MF__ MOD__"vinit"
  PUKT_CTRL_REC                  pUKT      = THIS_UKT_CTRL;
  PTASK_CTRL_REC                 pCurrTask = pUKT->pCTask;

  DBGIN_T (pCurrTask->ulTaskIndex);

  //
  // --- This is the first procedure called by the kernel code
  //
  sql51k_debug_break ( 1000 );

  if ( len != sizeof(RTE_COMM_REC) )
    {
    MSGD (( ERR_WRONG_COMM_REC_SIZE, len ))
    ABORT();
    }

  if (( pUKT->pCurrReq ) && ( pUKT->pCurrReq->ulReqType == REQ_INITOK ))
    {
    // --- Release the free list DLQ element which was used to awake the task.
    RELEASE_FREELIST_ELEM ( pUKT->pCurrReq );
    }

  //
  // --- initialize task control
  //
  sql70k_init_task_ctrl ( pCurrTask );

  // - alter task activ counters
  sql74k_alter_task_cnt( pCurrTask, ADD_ACTIVE_COUNTER );

  /* Remove inactive move lock */
  sql74k_long_term_move_lock( pCurrTask, TASK_IS_INACTIVE, false ); 

  // --- return address of the kernel communication record
  memset ( &pCurrTask->KernelCtrlRecord, 0, sizeof(pCurrTask->KernelCtrlRecord) );
  *rte_comm_ptr              = &pCurrTask->KernelCtrlRecord;

  pCurrTask->TaskState = TSK_RUNNING;

  DBGOUT_T (pCurrTask->ulTaskIndex);
  return;
  }

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

VOID vfinish ( VOID )
  {
  #undef  MF__
  #define MF__ MOD__"vfinish"

  DBGPAS;

  sql51k_finish ();

  return;
  }


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

tsp1_utility_startup  vutil_startup( VOID )
{
#undef  MF__
#define MF__ MOD__"tsp1_utility_startup"
    tsp1_utility_startup      tsp1usUtilStartup = (tsp1_utility_startup)SP1US_CONNECT;
#ifdef DEBUG_RTE
    PTASK_CTRL_REC           pTaskCtrl = THIS_UKT_CTRL->pCTask;
#endif

    DBGIN_T (pTaskCtrl->ulTaskIndex);

    if (
      ( kgs.pUT->pUserCommCtrl->ulConnected == 0 ) &&
      ( kgs.pUT->TaskType                   == TT_UT ) && 
        kgs.fWinShutdownPending )
    {
        MSGD (( INFO_AUTOSHUTDOWN, kgs.szServerDB ));
        tsp1usUtilStartup = SP1US_SHUTDOWN;
    }

    DBGOUT_T (pTaskCtrl->ulTaskIndex);
    return (tsp1usUtilStartup);
}

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

VOID  vrestart ( PROCESS_ID    pid,
                 tsp2_devname  sysdevspace )
{
#undef  MF__
#define MF__ MOD__"vrestart"
#ifdef DEBUG_RTE
    PTASK_CTRL_REC     pTaskCtrl = THIS_UKT_CTRL->pCTask;
#endif

    DBGIN_T (pTaskCtrl->ulTaskIndex);

#ifdef DEVELOP_CHECKS
     if ( (ULONG)pid != THIS_UKT_CTRL->pCTask->ulTaskIndex )
     {
         MSGD (( ERR_VXXXX_WRONG_TASK, "vrestart", pid ));
         DBG1 (( MF__, "[T:0x%03u] Wrong pid %u", pTaskCtrl->ulTaskIndex, pid ));
         ABORT();
     }
#endif

    kgs.fRestarted    = TRUE;

    if ( kgs.ulStartupOptions & FORCE_AUTORESTART )
    {
        RTE_CloseDiagPipe();
        sql61k_post_xstart_sem ( kgs.szServerDB, FALSE );
    }

    RTE_SetDatabaseState(SERVER_ONLINE_EO00);

    DBGOUT_T (pTaskCtrl->ulTaskIndex);
    return;
}

/*------------------------------*/
/* PTS 1115383 */
void  voffline ( tsp00_TaskId   pid,
                 SHUTDOWN_MODE  mode )
  {
  #undef  MF__
  #define MF__ MOD__"voffline"
  #ifdef DEVELOP_CHECKS
   PUKT_CTRL_REC                 pUKT      = THIS_UKT_CTRL;
   PTASK_CTRL_REC                pTaskCtrl = pUKT->pCTask;
  #else
   PTASK_CTRL_REC                pTaskCtrl = &kgs.pFirstTaskCtrl[pid - 1];
   PUKT_CTRL_REC                 pUKT      = pTaskCtrl->pUKT;
  #endif

  DBGPAS_T (pTaskCtrl->ulTaskIndex);

  #ifdef DEVELOP_CHECKS
   if ( (ULONG)pid != pTaskCtrl->ulTaskIndex )
     {
     MSGD (( ERR_VXXXX_WRONG_TASK, "voffline", pid ));
     DBG1 (( MF__, "[T:0x%03u] Wrong pid %u", pTaskCtrl->ulTaskIndex, pid ));
     ABORT();
     }
  #endif

  pTaskCtrl->TaskState = TSK_VSHUTDOWN;

  kgs.fRestarted = FALSE;

  if ( mode == SHUTDOWN_KILL )
  {
      kgs.dumpDiagFiles = true;
      MSGCD (( INFO_SHUTDOWN_KILL_REQ  ));
      *kgs.pDBState = SERVER_SHUTDOWNKILL;
  }
  else
  {
      MSGCD (( INFO_SHUTDOWN_NORMAL_REQ  ));
      *kgs.pDBState = SERVER_SHUTDOWN;
  }

  UPDATE_SERVICE_OR_CONSOLE_STATE(*kgs.pDBState);

  // --- wakeup coordinator thread
  sql41c_post_event_sem ( kgs.Coord.ThrdCtrlHeader.hevSem, "Coord" );

  if ( kgs.fWinShutdownPending )
  {
      /* Former implementation used wait on utility task TSK_INACTIVE state...
         But this would wait forever, since the utility task is blocked in a
         vsuspend that waits for a server task to complete its job... That server
         task will be terminated by 'EXITTHREAD'... */
      kgs.fWinShutdownCompleted = true;
      /* This new flag indicates the loop is terminated... */
  }

  EXITTHREAD( 0, pUKT->ThrdCtrlHeader.hThrd );
  }

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

VOID sql51k_finish ( VOID )
  {
  #undef  MF__
  #define MF__ MOD__"sql51k_finish"
  PUKT_CTRL_REC               pUKT       = THIS_UKT_CTRL;
  PTASK_CTRL_REC              pCurrTask  = pUKT->pCTask;

  DBGIN;

  /* Don't move this task during finish and next startup phase... */
  sql74k_long_term_move_lock( pCurrTask, TASK_IS_INACTIVE, true ); 

  // PTS 1110953
  if ( XPARAM(showMaxStackUse) )
  {
      vsShowMaxStackUse( pUKT->pCTask->ulTaskIndex, eo92GetTaskTypeName(pUKT->pCTask->TaskType) );
  }
  // - alter task activ counters
  sql74k_alter_task_cnt( pCurrTask, SUB_ACTIVE_COUNTER );

  switch ( pCurrTask->TaskType )
    {
    case TT_EV:
    case TT_UT:
    case TT_US:
    case TT_SV:
      // --- release the current task or fiber 
      //     this function should never return!!!
      sql88k_release_curr_task_or_fiber( &pUKT );

      //
      // --- we should never return here
      //
      break;

    case TT_TW:

      MSGD (( INFO_RELEASING_TRACEWRITER ));
      // --- preliminary: crash server after tracewriter wrote trace (and dump)
      switch ( *kgs.pDBState )
        {
        case SERVER_SHUTDOWN :
        case SERVER_SHUTDOWNKILL :
        case SERVER_SHUTDOWNREINIT :
        case SERVER_ABORT :
        case SERVER_KILL :
        case SERVER_STOP :
          pUKT->ThrdCtrlHeader.ThrdState = UKT_TERMINATED;
          pCurrTask->TaskState           = TSK_TERMINATED_EO00;
          ExitThread( 0 );
          break;
        }

      MSGD (( ERR_VFINISH_TW_DUR_NORM_OP, *kgs.pDBState ));
      ABORT();
      break;

    default:
      //
      // - only user tasks and the utility task should leave the kernel code
      //
      MSGD (( ERR_KERNELMAINPRG_RETURNED ));
      ABORT();
      break;
    }

  //
  // --- we should never return here
  //
  MSGD (( ERR_TASK_RETURNED ));
  ABORT();

  DBGOUT;
  return;
  }

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

BOOL  sql51k_auto_shutdown ( VOID )
{
#undef  MF__
#define MF__ MOD__"sql51k_auto_shutdown"
    PDLQ_REC      pRequest;
    static  BOOL  fAutoShutdownInProgress = FALSE;

    BOOLEAN volatile *pGracefully;

    DBGPAS;

    if (  pkss 
       && pkss->gracefully 
       && ( fAutoShutdownInProgress == FALSE ) 
       && ( *kgs.pDBState           == SERVER_WARM ) )
    {
        pGracefully = (BOOLEAN volatile *)&(pkss->gracefully);
        fAutoShutdownInProgress = TRUE;
        if ( kgs.fWinShutdownPending 
          || !RTE_SpawnRestartShutdown((void *)0) )
        {
            kgs.ulTerminationTimeOut    = sql50k_get_termination_timeout() / 3;

            if ( sql53k_comm_cancel ( kgs.pUT, commErrCrash_esp01 ))
            {
                while (( kgs.pUT->pUserCommCtrl->ulConnected != 0 )            &&
                       ( kgs.pUT->TaskState                  != TSK_INACTIVE ) &&
                       --kgs.ulTerminationTimeOut &&
                       *pGracefully )
                    SLEEP (1000);
            }

            if (  *pGracefully )
            {
                kgs.pUT->TaskState  = TSK_RUNNING;            

                if ( sql88k_create_task_or_fiber ( kgs.pUT ) == NO_ERROR )
                {
                    pRequest            = RESERVE_FREELIST_ELEM();
                    pRequest->ulReqType = REQ_INITOK;
                    sql74k_UKT_enqu_and_wake ( kgs.pUT->pUKT, kgs.pUT, pRequest );

                    kgs.ulTerminationTimeOut += (sql50k_get_termination_timeout() / 3) * 2;
  
                    while ( !kgs.fWinShutdownCompleted
                        &&  --kgs.ulTerminationTimeOut
                        &&  *pGracefully )
                        SLEEP (1000);
                }
            }
        }
        else
        {
            kgs.ulTerminationTimeOut    = sql50k_get_termination_timeout();

            while ( ( *kgs.pDBState == SERVER_WARM ) 
                    &&  --kgs.ulTerminationTimeOut
                    &&  *pGracefully )
                SLEEP (1000);
        }
    }

    kgs.ulTerminationTimeOut = 0;

    return ( !kgs.fRestarted );
}

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

VOID sql51k_debug_break ( ULONG ulDebugBreakPosition )
  {
  #undef  MF__
  #define MF__ MOD__"sql51k_debug_break"
  #ifdef DEBUG_RTE
   PTASK_CTRL_REC                pTaskCtrl = THIS_UKT_CTRL->pCTask;
  #endif

  DBGPAS_T (pTaskCtrl->ulTaskIndex);
  
  if ((kgs.ulSingleDebugBreakPos == ulDebugBreakPosition) ||
      (kgs.ulStaticDebugBreakPos == ulDebugBreakPosition))
    {
    if (kgs.ulSingleDebugBreakPos == ulDebugBreakPosition) 
      kgs.ulSingleDebugBreakPos = 0;

    if ( !(kgs.ulServiceType & SERVICE_INTERACTIVE_PROCESS) )
      {
      MSGALL (( WRN_NO_INTERACT_WITH_DESCTOP ));
      DBGOUT;
      return;
      }

    DebugBreak();
    }


  DBGOUT;
  return;
  }

/*
 * ========================== LOCAL FUNCTIONS =================================
 */

static VOID sql51k_start_multiple_tasks ( PTASK_CTRL_REC pFirstMultipleTask,
                                          ULONG          ulNumTasks )
{
  #undef  MF__
  #define MF__ MOD__"sql51k_start_multiple_tasks"

  ULONG                          uldx;
  PDLQ_REC                       pRequest;
  PTASK_CTRL_REC                 pTmpTaskCtrl;

  DBGIN;

  pTmpTaskCtrl = pFirstMultipleTask;
  for ( uldx = 0; uldx < ulNumTasks; uldx++ )
    {
    pRequest            = RESERVE_FREELIST_ELEM();
    pRequest->ulReqType = REQ_INITOK;
    sql73k_UKT_enqu ( pTmpTaskCtrl->pUKT, pTmpTaskCtrl, pRequest );
    pTmpTaskCtrl++;
    }

  DBGOUT;
  return;
}

/*
 * =============================== END ========================================
 */
