📄 task.c
字号:
** Make task runnable if task still suspended.
*/
if ( current_tcb->suspend_reason == WAIT_TSUSP )
{
/*
** Found the task being resumed... resume it.
*/
current_tcb->suspend_reason = WAIT_READY;
pthread_kill( current_tcb->pthrid, SIGCONT );
}
else
{
error = ERR_NOTSUSP;
}
}
else
error = ERR_OBJDEL;
sched_unlock();
return( error );
}
/*****************************************************************************
** t_getreg - retrieves the contents of the specified task notepad register
*****************************************************************************/
ULONG
t_getreg( ULONG tid, ULONG regnum, ULONG *reg_value )
{
p2pthread_cb_t *current_tcb;
p2pthread_cb_t *self_tcb;
ULONG error;
/*
** First ensure that the specified register is within range.
** ( We only support the eight user registers here. )
*/
if ( regnum < NUM_TASK_REGS )
{
error = ERR_NO_ERROR;
sched_lock();
if ( tid == 0 )
{
/*
** Use the notepad register set for the current task.
*/
self_tcb = my_tcb();
if ( self_tcb != (p2pthread_cb_t *)NULL )
{
/*
** Retrieve the value from the specified notepad register.
*/
*reg_value = self_tcb->registers[regnum];
}
else
error = ERR_OBJDEL;
}
else
{
/*
** If the task_list contains tasks, scan it for the tcb
** whose task id matches the one specified.
*/
current_tcb = tcb_for( tid );
if ( current_tcb != (p2pthread_cb_t *)NULL )
{
/*
** Found the specified task. Retrieve the
** value from the specified notepad register.
*/
*reg_value = current_tcb->registers[regnum];
}
else
error = ERR_OBJDEL;
}
sched_unlock();
}
else
{
/*
** Unsupported register was specified.
*/
error = ERR_REGNUM;
}
return( error );
}
/*****************************************************************************
** t_setreg - overwrites the contents of the specified task notepad register
** with the specified reg_value.
*****************************************************************************/
ULONG
t_setreg( ULONG tid, ULONG regnum, ULONG reg_value )
{
p2pthread_cb_t *current_tcb;
p2pthread_cb_t *self_tcb;
ULONG error;
/*
** First ensure that the specified register is within range.
** ( We only support the eight user registers here. )
*/
if ( regnum < NUM_TASK_REGS )
{
error = ERR_NO_ERROR;
sched_lock();
if ( tid == 0 )
{
/*
** Use the notepad register set for the current task
*/
self_tcb = my_tcb();
if ( self_tcb != (p2pthread_cb_t *)NULL )
{
/*
** Write the caller's value to the specified notepad register.
*/
self_tcb->registers[regnum] = reg_value;
}
else
error = ERR_OBJDEL;
}
else
{
/*
** If the task_list contains tasks, scan it for the tcb
** whose task id matches the one specified.
*/
current_tcb = tcb_for( tid );
if ( current_tcb != (p2pthread_cb_t *)NULL )
{
/*
** Found the specified task. Write the caller's
** value to the specified register.
*/
current_tcb->registers[regnum] = reg_value;
}
else
error = ERR_OBJDEL;
}
sched_unlock();
}
else
{
/*
** Unsupported register was specified.
*/
error = ERR_REGNUM;
}
return( error );
}
/*****************************************************************************
** t_setpri - sets a new priority for the specified task
*****************************************************************************/
ULONG
t_setpri( ULONG tid, ULONG pri, ULONG *oldpri )
{
p2pthread_cb_t *tcb;
int new_priority, sched_policy;
ULONG error;
error = ERR_NO_ERROR;
sched_lock();
tcb = tcb_for( tid );
if ( tcb != (p2pthread_cb_t *)NULL )
{
/*
** Save the previous priority level if the caller wants it.
*/
if ( oldpri != (ULONG *)NULL )
*oldpri = (ULONG)(tcb->prv_priority).sched_priority;
/*
** Translate the p2pthread priority into a pthreads priority
*/
pthread_attr_getschedpolicy( &(tcb->attr), &sched_policy );
new_priority = translate_priority( pri, sched_policy, &error );
/*
** Update the TCB with the new priority
*/
(tcb->prv_priority).sched_priority = new_priority;
/*
** If the selected task is not the currently-executing task,
** modify the pthread's priority now. If the selected task
** IS the currently-executing task, the sched_unlock operation
** will restore this task to the new priority level.
*/
if ( (tid != 0) && (tcb != my_tcb()) )
{
pthread_attr_setschedparam( &(tcb->attr), &(tcb->prv_priority) );
}
}
else
error = ERR_OBJDEL;
sched_unlock();
return( error );
}
/*****************************************************************************
** t_mode - sets the value of the calling task's mode flags
*****************************************************************************/
ULONG
t_mode( ULONG mask, ULONG new_flags, ULONG *old_flags )
{
p2pthread_cb_t *tcb;
int sched_policy;
ULONG error;
error = ERR_NO_ERROR;
pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,
(void *)&task_list_lock );
pthread_mutex_lock( &task_list_lock );
tcb = my_tcb();
if ( tcb != (p2pthread_cb_t *)NULL )
{
/*
** Save the previous priority level if the caller wants it.
*/
if ( old_flags != (ULONG *)NULL )
*old_flags = tcb->flags;
/*
** Change the task preemptibility status if specified
** to either allow the task to be preempted or to prevent
** preemption.
*/
pthread_mutex_unlock( &task_list_lock );
/*
** Note: modified from (mask & T_NOPREEMPT).
*/
if (mask & T_NOPREEMPT)
{
if ( (new_flags & T_NOPREEMPT) )
{
if ( !(tcb->flags & T_NOPREEMPT) )
sched_lock();
}
else
{
if ( (tcb->flags & T_NOPREEMPT) )
sched_unlock();
}
}
/*
** Determine whether round-robin time-slicing is to be used or not
*/
pthread_mutex_lock( &task_list_lock );
/*
** Note: modified from (mask & T_TSLICE).
*/
if (mask & T_TSLICE)
{
if ( new_flags & T_TSLICE )
sched_policy = SCHED_RR;
else
sched_policy = SCHED_FIFO;
pthread_attr_setschedpolicy( &(tcb->attr), sched_policy );
pthread_setschedparam( tcb->pthrid, sched_policy,
(struct sched_param *)&((tcb->attr).__schedparam) );
}
/*
** Update the mode flag bits in the TCB. First clear all the
** masked bits and then OR in the new bits.
*/
tcb->flags &= (~mask);
tcb->flags |= (new_flags & mask);
}
else
error = ERR_OBJDEL;
pthread_mutex_unlock( &task_list_lock );
pthread_cleanup_pop( 0 );
return( error );
}
/*****************************************************************************
** t_ident - identifies the specified p2pthread task
*****************************************************************************/
ULONG
t_ident( char name[4], ULONG node, ULONG *tid )
{
p2pthread_cb_t *current_tcb;
ULONG error;
error = ERR_NO_ERROR;
/*
** Validate the node specifier... only zero is allowed here.
*/
if ( node != 0L )
error = ERR_NODENO;
else
{
/*
** If task name string is a NULL pointer, return TID of current task.
*/
if ( name == (char *)NULL )
{
current_tcb = my_tcb();
*tid = current_tcb->taskid;
}
else
{
/*
** Scan the task list for a name matching the caller's name.
*/
for ( current_tcb = task_list;
current_tcb != (p2pthread_cb_t *)NULL;
current_tcb = current_tcb->nxt_task )
{
if ( (strncmp( name, current_tcb->taskname, 4 )) == 0 )
{
/*
** A matching name was found... return its TID
*/
*tid = current_tcb->taskid;
break;
}
}
if ( current_tcb == (p2pthread_cb_t *)NULL )
{
/*
** No matching name found... return caller's TID with error.
*/
current_tcb = my_tcb();
*tid = current_tcb->taskid;
error = ERR_OBJNF;
}
}
}
return( error );
}
/*****************************************************************************
** system initialization pthread
*****************************************************************************/
/*
void *init_system( void *dummy )
{
user_sysroot();
return( (void *)NULL );
}
*/
/*****************************************************************************
** p2pthread main program
**
** This function serves as the entry point to the p2pthread emulation
** environment. It serves as the parent process to all p2pthread tasks.
** This process creates an initialization thread and sets the priority of
** that thread to the highest allowable value. This allows the initialization
** thread to complete its work without being preempted by any of the task
** threads it creates.
*****************************************************************************/
/*
int main( int argc, char **argv )
{
int max_priority;
pthread_t tid_init;
pthread_attr_t init_attr;
struct sched_param init_priority;
*/
/*
** Get the maximum permissible priority level for the current OS.
*/
// max_priority = sched_get_priority_max( SCHED_FIFO );
/*
** Lock all memory pages associated with this process to prevent delays
** due to process (or thread) memory being swapped out to disk and back.
*/
// mlockall( (MCL_CURRENT | MCL_FUTURE) );
/*
** Initialize the thread attributes to default values.
** Then modify the attributes to make a real-time thread.
*/
// pthread_attr_init( &init_attr );
// pthread_attr_setschedpolicy( &init_attr, SCHED_FIFO );
/*
** Get the default scheduling priority & init init_priority
** This makes the initialization pthread the highest-priority thread
** in the p2pthread environment, and prevents premature preemption.
*/
/*
pthread_attr_getschedparam( &init_attr, &init_priority );
init_priority.sched_priority = max_priority;
pthread_attr_setschedparam( &init_attr, &init_priority );
printf( "\r\nStarting System Initialization Pthread" );
pthread_create( &tid_init, &init_attr,
init_system, (void *)NULL );
*/
/*
** Wait for the initialization thread to terminate and return.
*/
// pthread_join( tid_init, (void **)NULL );
// exit( 0 );
//}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -