createthread.c

来自「zilog的实时操作系统RZK,可以移植到多种处理器上」· C语言 代码 · 共 310 行

C
310
字号
/*
* File				:	CreateThread.c
*
* Description		:	Defines RZKCreateThread function.
* 
* Copyright 2004 ZiLOG Inc.  ALL RIGHTS RESERVED.
*
* This file contains unpublished confidential and proprietary information
* of ZiLOG, Inc.
* NO PART OF THIS WORK MAY BE DUPLICATED, STORED, PUBLISHED OR DISCLOSED 
* IN ANY FORM WITHOUT THE PRIOR WRITTEN CONSENT OF ZiLOG, INC.
* This is not a license and no use of any kind of this work is authorized
* in the absence of a written license granted by ZiLOG, Inc. in ZiLOG's 
* sole discretion 
*/
/* include files*/
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include "ZSysgen.h"
#include "ZTypes.h"
#include "ZThread.h"
#include "ZQueue.h"
#include "ZScheduler.h"
#include "externvar.h"
#include "ZInterrupt.h"

#define	pCurrentThread ((RZK_TCB_t *) hCurrentThread)
#ifdef RZK_TOOLSMITH
#define INIT_STACK_OFFSET 27
#else
#define INIT_STACK_OFFSET 27
#endif

/* Globals */
extern RZK_THREAD_CB_t nTcb[];	/* Changed on 08-05-03 */
/*dependencies*/
/** extern functions */
extern void* RZKMemcpy(void *, const void *, RZK_LENGTH_t); // IAR port, UINT changed to RZK_LENGTH_t
//extern void RZKScheduler();
extern void RZKInitStack(RZK_HANDLE_t *sp, RZK_TCB_t *pTCB, UINT8 nArgs, RZK_HANDLE_t *Args);

extern RZK_HANDLE_t AcquireControlBlock( RZK_TCB_t *, UINT, UINT) ;
extern void QueueAppend(RZK_TCB_t *pInsertionPosition,RZK_TCB_t *pObjectToAppend) ;
extern void DispatchQueueNodeAppend(RZK_TCB_t *pObjectToAppend) ;
extern void RZKSystemTimerIsrEntry();
/** extern variables */
extern RZK_THREADHANDLE_t hCurrentThread;     /* declared in Scheduler.c */
extern RZK_DISPATCHQ_t DispatchQueue[DMAX_PRIORITY_P1];/*declared in DispatchQinit.c*/
extern RZK_TIMEQ_t TimeQueue[TMAX_QUEUE];
extern const UINT32 pMap[32];
extern volatile UINT32 DQPriorityBitMap;
extern UINT8 uRegBankBusyBitMap;
extern TICK_t uDefaultTimeSlice;


// CWD IMPLEMENTATION
extern INT8 fsCwdPath[] ;
extern UINT8 fsEnable ;
extern INT8 fsCwdArray[1][1] ; 
// IAR port comment
//extern UINT nRzkMaxCwdPathLen ;

extern UINT8 fsInAppEntry ;


#ifdef RZK_NT
	static INT nThread;
	LPTHREAD_START_ROUTINE pEntryNT;
#endif


void InitCwdTable( void )
{
	if( fsEnable )
	{
		UINT nCnt ;
		RZK_TCB_t *ptr = (RZK_TCB_t * ) &nTcb[0] ;
		UINT8 *pCwdArray = ( UINT8 * ) &fsCwdArray[0][0];

		for( nCnt = 0 ; nCnt < MAX_THREADS; nCnt++, ptr++, pCwdArray += nRzkMaxCwdPathLen )
		{
			ptr->pFSCwd = pCwdArray ;
		}
	}
	return ;
}


/* Function Definition */
/* Function			:	RZKCreateThread
*
* Description		:	This function Creates an RZK Thread.
* 
* Inputs			:	RZK_NAME_t szName[8]		     NAME OF THE THREAD TO BE CREATED
*						RZK_PTR_t pEntryPoint		     POINTER TO THE ENTRY POINT OF THE FUNCTION
*						RZK_PTR_t pArgv 			     POINTER TO THE LIST OF ARGUMENTS OF THE ENTRYPOINT FUNCTION
*						RZK_PTR_t pCleanupFunctions      POINTER TO THE CLEANUP FUNCTIONS	
*						int* pInitialStack			 CURRENT  STACK POINTTER LOCATION 
*						RZK_THREAD_PRIORITY_t cPriority  GLOBAL THREAD PRIORITY VARIABLE  
*						TICK_t tQuantum                  THREAD RUN TIME QUANTUM							
*						RZK_OPERATIONMODE_t uOperationMode	OPERATION MODE FLAG FOR THE NEW THRAD	
*							
* Outputs			:	pTcb - Pointer to the TCB of type RZK_THREADHANDLE_t if success
*						NULL - if unsuccessful	
*
* Dependencies		:	None.
*/
RZK_THREADHANDLE_t RZKCreateThread
(
	RZK_NAME_t szName[MAX_OBJECT_NAME_LEN],  
//	RZK_PTR_t pEntryPoint,  // For IAR PORT
	RZK_PTR_t pEntryPoint, // For IAR PORT
        FNP_THREAD_ENTRY *pCleanupFunction, // IAR port
//					VOID (**pCleanupFunction) (),
	CADDR_t pInitialStack,				
	RZK_THREAD_PRIORITY_t cPriority, 
	TICK_t tQuantum,							
	RZK_OPERATIONMODE_t uOperationMode,
	UINT8 nArgs,
	...
)
{
	/* Start of the Create Thread Function. */ 

	RZK_TCB_t *pTCB;
        UINT8 *args;
	args = &nArgs;
#ifdef RZK_DEBUG
	if (pEntryPoint == NULL) 
	{
		pCurrentThread->errNum = RZKERR_INVALID_ARGUMENTS;
		return  NULL;
	}

	if (pInitialStack == NULL)
	{
		pCurrentThread->errNum = RZKERR_INVALID_STACK;
		return NULL;
	}

	if(pEntryPoint != (RZK_PTR_t)RZKSystemTimerIsrEntry)
	if (cPriority < DMIN_PRIORITY || cPriority > DMAX_PRIORITY) 
	{
		pCurrentThread->errNum = RZKERR_INVALID_PRIORITY;
		return NULL;
	}

	if( (uOperationMode & RZK_THREAD_INTERRUPT) &&
		(uOperationMode & RZK_THREAD_AUTOSTART) )
	{
		pCurrentThread->errNum = RZKERR_INVALID_ARGUMENTS;
		return  NULL;
	}
#endif		/* for RZK_DEBUG */
	
	/* Call AcquireControlBlock Function */

	pTCB = (RZK_TCB_t *) AcquireControlBlock( (RZK_TCB_t *)&nTcb[0], MAX_THREADS,sizeof(RZK_TCB_t)); /* &nTcb[0] Changed on 08-05-03 */

	
#ifndef RZK_PERFORMANCE
	
	if (pTCB == NULL)
	{
		pCurrentThread->errNum = RZKERR_CB_UNAVAILABLE;
		return NULL;
	}
	else pCurrentThread->errNum = RZKERR_SUCCESS;

#endif /* RZK_PERFORMANCE_DEBUG */

	/* SETTING Tcb VALUES */

#ifdef RZK_DEBUG
	pTCB -> magic_num = MAGIC_NUM_THREAD;
#endif

#ifdef RZK_NT
	pEntryNT = (LPTHREAD_START_ROUTINE)pEntryPoint;
	pTCB->hNTThread = (void *) CreateThread(NULL, 0, pEntryNT, NULL, CREATE_SUSPENDED |THREAD_SUSPEND_RESUME, &(pTCB->ThreadID[nThread++]));
#endif

#ifdef RZK_KERNEL_AWARE
	if(szName == NULL)
		RZKMemcpy(pTCB->szName, "NoName", MAX_OBJECT_NAME_LEN);
	else		
		RZKMemcpy(pTCB->szName, szName, MAX_OBJECT_NAME_LEN);

	if(strlen((char *)szName) >= MAX_OBJECT_NAME_LEN)
	{
		pCurrentThread->errNum = RZKERR_INVALID_SIZE;
		pTCB->uState = 0;
		return NULL;
	}	
#endif /* KERNEL_AWARE */ 
	
	/* setting the dispatch priority */
	
//	pTCB->cDispPriority = (pTCB->RZK_INIT.cGlobalPriority = pTCB->cGlobalPriority = cPriority) >> 2;
	/* Now only dispatch priroity concept remains in RZK1.1 release */
	pTCB->cDispPriority = cPriority;
	
	/* Setting the original priority and the inherited priority for priority inheritance */
	#ifdef RZK_PRIORITYINHERITANCE
		pTCB -> uOriginalPriority = pTCB-> cDispPriority;
		pTCB -> cInheritedPriority = DMAX_PRIORITY;
		pTCB -> pOwnedResNext = NULL;
	#endif /* End of RZK_PRIORITYINHERITANCE */
 

	
	/* setting the Operation Mode */	
	pTCB->uOperationMode = pTCB->RZK_INIT.uOperationMode = uOperationMode;  

	if ( tQuantum == (TICK_t ) 0 ) /* if tQuantum = 0, then default timeslice */
	{
		pTCB->RZK_INIT.tInitialQuantum = 0;
		pTCB->tRRTime = pTCB->tQuantum = uDefaultTimeSlice;
	}
	else
	pTCB->tRRTime = pTCB->RZK_INIT.tInitialQuantum = pTCB->tQuantum = tQuantum;

#ifdef RZK_STATISTIC
	pTCB->RZK_STATISTICS.tTotalTimeRun = 0;
	pTCB->RZK_STATISTICS.tActualTimeRun = 0;
	pTCB->RZK_STATISTICS.nNumTimesBlocked = 0;
#endif

//	pTCB->RZK_INIT.pArgv = pArg;

	/* The program Counter will point to the start of the function.*/
	pTCB->pFuncEntryPoint = pEntryPoint;

	/* Also initialize the cleanup fuctions.*/
	pTCB->pCleanupFunc = pCleanupFunction;

	pTCB->hObject = NULL;
	pTCB->uBankSelector = 0;

	/* Initialize the adjacent threads while in resource queue to NULL*/
	pTCB->pResNext = pTCB->pResPrevious = ( RZK_TCB_t *) NULL;

	/* set the pBlockingResource to NULL*/
	pTCB->pBlockingResource = NULL;

	/* Some initializations when thread gets created. Old thread's values must not be retained here */
	pTCB->tWaitTime = 0;
	pTCB->errNum = RZKERR_SUCCESS;
	pTCB->pMessage = NULL;
	pTCB->uMessageSize = 0;
	pTCB->eEventsReceived = 0;
	pTCB->eEventsRequested = 0;
	pTCB->etEventOperation = (RZK_EVENT_OPERATION_et) 0;
	pTCB->uSegSize = 0;
	pTCB->pSeg = NULL;
	pTCB->pOwnedSegNext = NULL;
	/* Some initializations when thread gets created. Old thread's values must not be retained here */

	pTCB->hObject = (RZK_HANDLE_t) pTCB;

	/*Initialize the stack pointer to the position of the pInitStack. */
#ifdef _IAR_CODE
        if(nArgs > 3)
        	pTCB->pInitialStack = (pInitialStack -= (INIT_STACK_OFFSET + ((nArgs - 3)*3))); //space for arguments
        else
        	pTCB->pInitialStack = (pInitialStack -= INIT_STACK_OFFSET); //space for arguments
#else
			pTCB->pInitialStack = (pInitialStack -= (INIT_STACK_OFFSET + (nArgs*3))); //space for arguments
#endif        
	RZKInitStack((RZK_HANDLE_t *) pInitialStack, pTCB, nArgs,(RZK_HANDLE_t *)(&args[3]));

	/* set CREATED field in uState also */	
	pTCB->uState = OBJECT_CREATED | OBJECT_BUSY | THREAD_INFINITESUSPEND;

	// FS CWD related inheritation
	if( fsEnable )
	{
		if( fsInAppEntry == RZK_TRUE )
		{
			// copy the configured string here...
			RZKMemcpy( ( void * ) pTCB->pFSCwd, ( const void * ) fsCwdPath, nRzkMaxCwdPathLen ) ;
		}
		else
		{
			// copy the calling threads string here...
			RZKMemcpy( ( void * ) pTCB->pFSCwd, ( const void * ) pCurrentThread->pFSCwd, nRzkMaxCwdPathLen ) ;
		}
	}

	/* Below code gets executed only if there is no interrupt mode and AUTOSTART option is
	specified for the thread */
	if(pTCB->uOperationMode & RZK_THREAD_AUTOSTART)
	/* IF Autostart, add the thread to Dispatch Queue */
	{
		UINTRMASK mInterruptMask;
		mInterruptMask = RZKDisableInterrupts();
		DispatchQueueNodeAppend(pTCB);
		/* Set the RUNNING bit */
		pTCB->uState = OBJECT_CREATED | OBJECT_BUSY | THREAD_RUNNING;
		RZKEnableInterrupts(mInterruptMask);

		mInterruptMask = RZKDisableInterrupts();
		RZKScheduler();
		RZKEnableInterrupts(mInterruptMask);
	} /* End of AUTOSTART */
	return  ((RZK_THREADHANDLE_t) pTCB);

}	/* End of CreateThread */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?