示例#1
0
文件: mutex.c 项目: yuki74w/TRON
/*
 * Create mutex
 */
SYSCALL ID _tk_cre_mtx( CONST T_CMTX *pk_cmtx )
{
#if CHK_RSATR
	const ATR VALID_MTXATR = {
		 TA_CEILING
		|TA_NODISWAI
#if USE_OBJECT_NAME
		|TA_DSNAME
#endif
	};
#endif
	MTXCB	*mtxcb;
	ID	mtxid;
	INT	ceilpri;
	ER	ercd;

	CHECK_RSATR(pk_cmtx->mtxatr, VALID_MTXATR);

	if ( (pk_cmtx->mtxatr & TA_CEILING) == TA_CEILING ) {
		CHECK_PRI(pk_cmtx->ceilpri);
		ceilpri = int_priority(pk_cmtx->ceilpri);
	} else {
		ceilpri = 0;
	}

	BEGIN_CRITICAL_SECTION;
	/* Get control block from FreeQue */
	mtxcb = (MTXCB*)QueRemoveNext(&free_mtxcb);
	if ( mtxcb == NULL ) {
		ercd = E_LIMIT;
	} else {
		mtxid = ID_MTX(mtxcb - mtxcb_table);

		/* Initialize control block */
		QueInit(&mtxcb->wait_queue);
		mtxcb->mtxid   = mtxid;
		mtxcb->exinf   = pk_cmtx->exinf;
		mtxcb->mtxatr  = pk_cmtx->mtxatr;
		mtxcb->ceilpri = ceilpri;
		mtxcb->mtxtsk  = NULL;
		mtxcb->mtxlist = NULL;
#if USE_OBJECT_NAME
		if ( (pk_cmtx->mtxatr & TA_DSNAME) != 0 ) {
			strncpy((char*)mtxcb->name, (char*)pk_cmtx->dsname,
				(UINT)OBJECT_NAME_LENGTH);
		}
#endif
		ercd = mtxid;
	}
	END_CRITICAL_SECTION;

	return ercd;
}
示例#2
0
文件: mutex.c 项目: yuki74w/TRON
/*
 * Limit the priority change by mutex at task priority change
 *    1.If the 'tcb' task locks mutex, cannot set lower priority than the
 *	highest priority in all mutexes which hold lock. In such case,
 *	return the highest priority of locked mutex.
 *    2.If mutex with TA_CEILING attribute is locked or waiting to be locked,
 *	cannot set higher priority than the lowest within the highest
 *	priority limit of mutex with TA_CEILING attribute.
 *	In this case, return E_ILUSE.
 *    3.Other than above, return the 'priority'.
 */
EXPORT INT chg_pri_mutex( TCB *tcb, INT priority )
{
	MTXCB	*mtxcb;
	INT	hi_pri, low_pri, pri;

	hi_pri  = priority;
	low_pri = int_priority(MIN_PRI);

	/* Mutex lock wait */
	if ( (tcb->state & TS_WAIT) != 0 && (tcb->wspec->tskwait & TTW_MTX) != 0 ) {
		mtxcb = get_mtxcb(tcb->wid);
		if ( (mtxcb->mtxatr & TA_CEILING) == TA_CEILING ) {
			pri = mtxcb->ceilpri;
			if ( pri > low_pri ) {
				low_pri = pri;
			}
		}
	}

	/* Locked Mutex */
	pri = hi_pri;
	for ( mtxcb = tcb->mtxlist; mtxcb != NULL; mtxcb = mtxcb->mtxlist ) {
		switch ( mtxcb->mtxatr & TA_CEILING ) {
		  case TA_CEILING:
			pri = mtxcb->ceilpri;
			if ( pri > low_pri ) {
				low_pri = pri;
			}
			break;
		  case TA_INHERIT:
			if ( mtx_waited(mtxcb) ) {
				pri = mtx_head_pri(mtxcb);
			}
			break;
		  default: /* TA_TFIFO, TA_TPRI */
			/* nothing to do */
			break;
		}
		if ( pri < hi_pri ) {
			hi_pri = pri;
		}
	}

	if ( priority < low_pri ) {
		return E_ILUSE;
	}
	return hi_pri;
}
示例#3
0
/*
 * Change task priority
 */
SYSCALL ER _tk_chg_pri( ID tskid, PRI tskpri )
{
	TCB	*tcb;
	INT	priority;
	ER	ercd;

	CHECK_TSKID_SELF(tskid);
	CHECK_PRI_INI(tskpri);

	tcb = get_tcb_self(tskid);

	BEGIN_CRITICAL_SECTION;
	if ( tcb->state == TS_NONEXIST ) {
		ercd = E_NOEXS;
		goto error_exit;
	}

	/* Conversion priority to internal expression */
	if ( tskpri == TPRI_INI ) {
		priority = tcb->ipriority;
	} else {
		priority = int_priority(tskpri);
	}

#ifdef NUM_MTXID
	/* Mutex priority change limit */
	ercd = chg_pri_mutex(tcb, priority);
	if ( ercd < E_OK ) {
		goto error_exit;
	}

	tcb->bpriority = (UB)priority;
	priority = ercd;
#else
	tcb->bpriority = priority;
#endif

	/* Change priority */
	change_task_priority(tcb, priority);

	ercd = E_OK;
    error_exit:
	END_CRITICAL_SECTION;

	return ercd;
}
示例#4
0
/*
 * Rotate ready queue
 */
SYSCALL ER _tk_rot_rdq( PRI tskpri )
{
	CHECK_PRI_RUN(tskpri);

	BEGIN_CRITICAL_SECTION;
	if ( tskpri == TPRI_RUN ) {
		if ( in_indp() ) {
			rotate_ready_queue_run();
		} else {
			rotate_ready_queue(ctxtsk->priority);
		}
	} else {
		rotate_ready_queue(int_priority(tskpri));
	}
	END_CRITICAL_SECTION;

	return E_OK;
}
示例#5
0
文件: task.c 项目: Ninals-GitHub/TRON
/*
 * Refer ready queue
 */
SYSCALL INT _td_rdy_que( PRI pri, ID list[], INT nent )
{
	QUEUE	*q, *tskque;
	INT	n = 0;

	CHECK_PRI(pri);

	BEGIN_DISABLE_INTERRUPT;
	tskque = &ready_queue.tskque[int_priority(pri)];
	for ( q = tskque->next; q != tskque; q = q->next ) {
		if ( n++ < nent ) {
			*(list++) = ((TCB*)q)->tskid;
		}
	}
	END_DISABLE_INTERRUPT;

	return n;
}
示例#6
0
/*
 * Create task
 */
SYSCALL ID _tk_cre_tsk P1( CONST T_CTSK *pk_ctsk )
{
#if CHK_RSATR
	const ATR VALID_TSKATR = {	/* Valid value of task attribute */
		 TA_HLNG
		|TA_SSTKSZ
		|TA_USERSTACK
		|TA_TASKSPACE
		|TA_RESID
		|TA_RNG3
		|TA_FPU
		|TA_COP0
		|TA_COP1
		|TA_COP2
		|TA_COP3
		|TA_GP
#if USE_OBJECT_NAME
		|TA_DSNAME
#endif
	};
#endif
	TCB	*tcb;
	INT	stksz, sstksz, sysmode, resid;
	void	*stack = NULL, *sstack;
	ER	ercd;

	CHECK_RSATR(pk_ctsk->tskatr, VALID_TSKATR);
	CHECK_PRI(pk_ctsk->itskpri);
	CHECK_NOCOP(pk_ctsk->tskatr);
#if USE_SINGLE_STACK
	CHECK_NOSPT((pk_ctsk->tskatr & TA_USERSTACK) == 0);
#endif
#if CHK_PAR
	if ( (pk_ctsk->tskatr & TA_USERSTACK) != 0 ) {
		CHECK_PAR((pk_ctsk->tskatr & TA_RNG3) != TA_RNG0);
		CHECK_PAR(pk_ctsk->stksz == 0);
	} else {
		CHECK_PAR(pk_ctsk->stksz >= 0);
	}
	if ( (pk_ctsk->tskatr & TA_TASKSPACE) != 0 ) {
		CHECK_PAR(pk_ctsk->lsid >= 0 && pk_ctsk->lsid <= MAX_LSID);
	}
#endif

	if ( (pk_ctsk->tskatr & TA_RESID) != 0 ) {
		CHECK_RESID(pk_ctsk->resid);
		resid = pk_ctsk->resid;
	} else {
		resid = SYS_RESID; /* System resource group */
	}

	if ( (pk_ctsk->tskatr & TA_SSTKSZ) != 0 ) {
		CHECK_PAR(pk_ctsk->sstksz >= MIN_SYS_STACK_SIZE);
		sstksz = pk_ctsk->sstksz;
	} else {
		sstksz = default_sstksz;
	}
	if ( (pk_ctsk->tskatr & TA_RNG3) == TA_RNG0 ) {
		sysmode = 1;
		sstksz += pk_ctsk->stksz;
		stksz = 0;
	} else {
		sysmode = 0;
#if USE_SINGLE_STACK
		sstksz += pk_ctsk->stksz;
		stksz = 0;
#else
		stksz = pk_ctsk->stksz;
#endif
	}

	/* Adjust stack size by 8 bytes */
	sstksz = (sstksz + 7) / 8 * 8;
	stksz  = (stksz  + 7) / 8 * 8;

	/* Allocate system stack area */
	sstack = IAmalloc((UINT)sstksz, TA_RNG0);
	if ( sstack == NULL ) {
		return E_NOMEM;
	}

	if ( stksz > 0 ) {
		/* Allocate user stack area */
		stack = IAmalloc((UINT)stksz, pk_ctsk->tskatr);
		if ( stack == NULL ) {
			IAfree(sstack, TA_RNG0);
			return E_NOMEM;
		}
	}

	BEGIN_CRITICAL_SECTION;
	/* Get control block from FreeQue */
	tcb = (TCB*)QueRemoveNext(&free_tcb);
	if ( tcb == NULL ) {
		ercd = E_LIMIT;
		goto error_exit;
	}

	/* Initialize control block */
	tcb->exinf     = pk_ctsk->exinf;
	tcb->tskatr    = pk_ctsk->tskatr;
	tcb->task      = pk_ctsk->task;
	tcb->ipriority = (UB)int_priority(pk_ctsk->itskpri);
	tcb->resid     = resid;
	tcb->stksz     = stksz;
	tcb->sstksz    = sstksz;
#if USE_OBJECT_NAME
	if ( (pk_ctsk->tskatr & TA_DSNAME) != 0 ) {
		STRNCPY((char*)tcb->name, (char*)pk_ctsk->dsname, OBJECT_NAME_LENGTH);
	}
#endif
#if TA_GP
	/* Set global pointer */
	if ( (pk_ctsk->tskatr & TA_GP) != 0 ) {
		gp = pk_ctsk->gp;
	}
	tcb->gp = gp;
#endif

	/* Set stack pointer */
	if ( stksz > 0 ) {
		tcb->istack = (VB*)stack + stksz;
	} else {
		tcb->istack = pk_ctsk->stkptr;
	}
	tcb->isstack = (VB*)sstack + sstksz - RESERVE_SSTACK(tcb->tskatr);

	/* Set initial value of task operation mode */
	tcb->isysmode = (B)sysmode;
	tcb->sysmode  = (H)sysmode;

	/* Set initial value of task space */
	if ( (pk_ctsk->tskatr & TA_TASKSPACE) != 0 ) {
		tcb->tskctxb.uatb = pk_ctsk->uatb;
		tcb->tskctxb.lsid = pk_ctsk->lsid;
	} else {
		tcb->tskctxb.uatb = NULL;
		tcb->tskctxb.lsid = 0;		/* Task Space */
	}

	/* make it to DORMANT state */
	make_dormant(tcb);

	ercd = tcb->tskid;

    error_exit:
	END_CRITICAL_SECTION;

	if ( ercd < E_OK ) {
		IAfree(sstack, TA_RNG0);
		if ( stksz > 0 ) {
			IAfree(stack, pk_ctsk->tskatr);
		}
	}

	return ercd;
}
/*
 * Create task
 */
SYSCALL ID tk_cre_tsk_impl P1( T_CTSK *pk_ctsk )
{
#if CHK_RSATR
	const ATR VALID_TSKATR = {	/* Valid value of task attribute */
		 TA_HLNG
		|TA_RNG3
		|TA_USERBUF
		|TA_GP
#if USE_OBJECT_NAME
		|TA_DSNAME
#endif
	};
#endif
	TCB	*tcb;
	W	sstksz;
	VP	stack;
	ER	ercd;

	CHECK_RSATR(pk_ctsk->tskatr, VALID_TSKATR);
#if !USE_IMALLOC
	/* TA_USERBUF must be specified if configured in no Imalloc */
	CHECK_PAR((pk_ctsk->tskatr & TA_USERBUF) != 0);
#endif
	CHECK_PRI(pk_ctsk->itskpri);
	CHECK_PAR(pk_ctsk->stksz >= MIN_SYS_STACK_SIZE);

	/* Adjust stack size by 8 bytes */
	sstksz  = (pk_ctsk->stksz  + 7) / 8 * 8;

#if USE_IMALLOC
	if ( (pk_ctsk->tskatr & TA_USERBUF) != 0 ) {
		/* Size of User buffer must be multiples of 8 */
		if ( sstksz != pk_ctsk->stksz ) {
			return E_PAR;
		}
		/* Use user buffer */
		stack = pk_ctsk->bufptr;
	} else {
		/* Allocate system stack area */
		stack = knl_Imalloc((UW)sstksz);
		if ( stack == NULL ) {
			return E_NOMEM;
		}
	}
#else
	/* Size of User buffer must be multiples of 8 */
	if ( sstksz != pk_ctsk->stksz ) {
		return E_PAR;
	}
	/* Use user buffer */
	stack = pk_ctsk->bufptr;
#endif

	BEGIN_CRITICAL_SECTION;
	/* Get control block from FreeQue */
	tcb = (TCB*)QueRemoveNext(&knl_free_tcb);
	if ( tcb == NULL ) {
		ercd = E_LIMIT;
		goto error_exit;
	}

	/* Initialize control block */
	tcb->exinf     = pk_ctsk->exinf;
	tcb->tskatr    = pk_ctsk->tskatr & ~TA_RNG3; /* handling as TA_RNG0 */
	tcb->task      = pk_ctsk->task;
	tcb->ipriority = (UB)int_priority(pk_ctsk->itskpri);
	tcb->sstksz    = sstksz;
#if USE_OBJECT_NAME
	if ( (pk_ctsk->tskatr & TA_DSNAME) != 0 ) {
		strncpy((char*)tcb->name, (char*)pk_ctsk->dsname, OBJECT_NAME_LENGTH);
	}
#endif
#if TA_GP
	/* Set global pointer */
	if ( (pk_ctsk->tskatr & TA_GP) != 0 ) {
		gp = pk_ctsk->gp;
	}
	tcb->gp = gp;
#endif

	/* Set stack pointer */
	tcb->isstack = (VB*)stack + sstksz;

	/* Set initial value of task operation mode */
	tcb->isysmode = 1;
	tcb->sysmode  = 1;

	/* make it to DORMANT state */
	knl_make_dormant(tcb);

	ercd = tcb->tskid;

    error_exit:
	END_CRITICAL_SECTION;

#if USE_IMALLOC
	if ( (ercd < E_OK) && ((pk_ctsk->tskatr & TA_USERBUF) == 0) ) {
		knl_Ifree(stack);
	}
#endif

	return ercd;
}