📄 task.c
字号:
sleep( 1 );#endif (*task_ptr)( parmblk->parms[0], parmblk->parms[1], parmblk->parms[2], parmblk->parms[3] ); /* ** Note: here the arg is '1'.
** If for some reason the task above DOES return, clean up the
** pthread and task resources and kill the pthread. */ pthread_cleanup_pop( 1 ); /* ** NOTE t_delete takes no action if the task has already been deleted. */ t_delete( tcb->taskid ); return( (void *)NULL );}/******************************************************************************* t_create - creates a pthread to contain the specified p2pthread task and** initializes the requisite data structures to support p2pthread ** task behavior not directly supported by Posix threads.*****************************************************************************/ULONG t_create( char name[4], ULONG pri, ULONG sstack, ULONG ustack, ULONG mode, ULONG *tid ){ p2pthread_cb_t *tcb; p2pthread_cb_t *current_tcb; int i, new_priority; ULONG error, my_tid; error = ERR_NO_ERROR; /* ** Establish task identifier */ my_tid = new_tid(); if ( tid != (ULONG *)NULL ) *tid = my_tid; /* First allocate memory for a new pthread task control block */ tcb = ts_malloc( sizeof( p2pthread_cb_t ) ); if ( tcb != (p2pthread_cb_t *)NULL ) { pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&task_list_lock ); pthread_mutex_lock( &task_list_lock ); /* ** Got a new task control block. Initialize it. */ tcb->pthrid = (pthread_t)NULL; tcb->taskid = my_tid; /* ** Copy the task name */ for ( i = 0; i < 4; i++ ) tcb->taskname[i] = name[i]; /* ** Initialize the thread attributes to default values. ** Then modify the attributes to make a real-time thread. */ pthread_attr_init( &(tcb->attr) ); /* ** Get the default scheduling priority & init prv_priority member */ pthread_attr_getschedparam( &(tcb->attr), &(tcb->prv_priority) ); /* ** Translate the p2pthread priority into a pthreads priority ** and set the new scheduling priority. */ pthread_attr_setschedpolicy( &(tcb->attr), SCHED_FIFO ); new_priority = translate_priority( pri, SCHED_FIFO, &error ); (tcb->prv_priority).sched_priority = new_priority; pthread_attr_setschedparam( &(tcb->attr), &(tcb->prv_priority) ); /* ** 'Registers' for task */ for ( i = 1; i < 8; i++ ) tcb->registers[i] = (ULONG)NULL; /* ** Mutex and Condition variable for task events */ pthread_mutex_init( &(tcb->event_lock), (pthread_mutexattr_t *)NULL ); pthread_cond_init( &(tcb->event_change), (pthread_condattr_t *)NULL ); /* ** Event state to awaken task (if suspended) */ tcb->event_mask = (ULONG)NULL; /* ** Current state of captured event flags for task */ tcb->events_captured = (ULONG)NULL; /* ** Current state of pending event flags for task */ tcb->events_pending = (ULONG)NULL; /* ** The task is initially created in a suspended state */ tcb->suspend_reason = WAIT_TSTRT; tcb->suspend_list = (p2pthread_cb_t **)NULL; tcb->nxt_susp = (p2pthread_cb_t *)NULL; tcb->nxt_task = (p2pthread_cb_t *)NULL; /* ** If everything's okay thus far, we have a valid TCB ready to go. */ if ( error == ERR_NO_ERROR ) { /* ** Insert the task control block into the task list. ** First see if the task list contains any tasks yet. */ if ( task_list == (p2pthread_cb_t *)NULL ) { task_list = tcb; } else { /* ** Append the new tcb to the task list. */ for ( current_tcb = task_list; current_tcb->nxt_task != (p2pthread_cb_t *)NULL; current_tcb = current_tcb->nxt_task ); current_tcb->nxt_task = tcb; } } else { /* ** OOPS! Something went wrong... clean up & exit. */ ts_free( (void *)tcb ); } pthread_mutex_unlock( &task_list_lock ); pthread_cleanup_pop( 0 ); } else /* malloc failed */ { error = ERR_OBJTFULL; } return( error );}/******************************************************************************* t_start - creates a pthread to contain the specified p2pthread task and** initializes the requisite data structures to support p2pthread ** task behavior not directly supported by Posix threads.*****************************************************************************/ULONG t_start( ULONG tid, ULONG mode, void (*task)( ULONG, ULONG, ULONG, ULONG ), ULONG parms[4] ){ p2pthread_cb_t *tcb; p2pthread_pb_t *parmblk; int sched_policy; ULONG error; error = ERR_NO_ERROR; /* ** 'Lock the p2pthread scheduler' to defer any context switch to a higher ** priority task until after this call has completed its work. */ sched_lock(); tcb = tcb_for( tid ); if ( tcb != (p2pthread_cb_t *)NULL ) { /* ** Found our task control block. ** Init the parameter block for the task wrapper function and ** start a new real-time pthread for the task. */ if ( tcb->suspend_reason == WAIT_TSTRT ) { tcb->suspend_reason = WAIT_READY; tcb->entry_point = task; /* ** Mode flags for task */ tcb->flags = mode; pthread_attr_init(&(tcb->attr)); /* ** Determine whether round-robin time-slicing is to be used or not */ if ( mode & T_TSLICE ) sched_policy = SCHED_RR; else sched_policy = SCHED_FIFO; pthread_attr_setschedpolicy( &(tcb->attr), sched_policy ); parmblk = (p2pthread_pb_t *)ts_malloc( sizeof( p2pthread_pb_t ) ); if ( parmblk != (p2pthread_pb_t *)NULL ) { parmblk->tcb = tcb; parmblk->task_ptr = task; if ( parms != (ULONG *)NULL ) { parmblk->parms[0] = parms[0]; parmblk->parms[1] = parms[1]; parmblk->parms[2] = parms[2]; parmblk->parms[3] = parms[3]; } else { parmblk->parms[0] = (ULONG)NULL; parmblk->parms[1] = (ULONG)NULL; parmblk->parms[2] = (ULONG)NULL; parmblk->parms[3] = (ULONG)NULL; }#ifdef DIAG_PRINTFS printf( "\r\nt_start task @ %p tcb @ %p:", task, tcb );#endif// if ( pthread_create( &(tcb->pthrid), &(tcb->attr),// task_wrapper, (void *)parmblk ) != 0 ) if ( pthread_create( &(tcb->pthrid), NULL, task_wrapper, (void *)parmblk ) != 0 ) {#ifdef DIAG_PRINTFS perror( "\r\nt_start pthread_create returned error:" );#endif error = ERR_OBJDEL; tcb_delete( tcb ); } } else {#ifdef DIAG_PRINTFS printf( "\r\nt_start unable to allocate parameter block" );#endif error = ERR_OBJDEL; tcb_delete( tcb ); } } else { /* ** task already made runnable */ error = ERR_ACTIVE;#ifdef DIAG_PRINTFS printf( "\r\nt_start task @ tcb %p already active", tcb );#endif } } else error = ERR_OBJDEL; /* ** 'Unlock the p2pthread scheduler' to enable a possible context switch ** to a task made runnable by this call. */ sched_unlock(); return( error );}/******************************************************************************* t_suspend - suspends the specified p2pthread task*****************************************************************************/ULONG t_suspend( ULONG tid ){ p2pthread_cb_t *current_tcb; p2pthread_cb_t *self_tcb; ULONG error; error = ERR_NO_ERROR; self_tcb = my_tcb(); if ( tid == 0 ) { /* ** Suspend currently executing task... get its pthread ID */ if ( self_tcb != (p2pthread_cb_t *)NULL ) { /* ** Don't suspend if currently executing task has the ** scheduler locked! */ pthread_mutex_lock( &p2pt_sched_lock ); if ( scheduler_locked == pthread_self() ) { if ( sched_lock_level < 1L ) { /* ** Suspend the currently executing task's pthread */ pthread_mutex_unlock( &p2pt_sched_lock ); self_tcb->suspend_reason = WAIT_TSUSP; pthread_kill( self_tcb->pthrid, SIGSTOP ); } else
/*
** Note: it seems that this condition did not suspend
** the task and no errno returned.
*/ pthread_mutex_unlock( &p2pt_sched_lock ); } else { /* ** Suspend the currently executing task's pthread */ pthread_mutex_unlock( &p2pt_sched_lock ); self_tcb->suspend_reason = WAIT_TSUSP; pthread_kill( self_tcb->pthrid, SIGSTOP ); } } } else { /* ** Suspend the task whose taskid matches tid. ** If the task_list contains tasks, scan it for the tcb ** whose task id matches the one to be suspended. */ current_tcb = tcb_for( tid ); if ( current_tcb != (p2pthread_cb_t *)NULL ) { /* ** Suspend task if task not already suspended. */ if ( current_tcb->suspend_reason != WAIT_TSUSP ) {
/*
** set this pthread as the hignest priority, so
that the tid task are not locked.
*/ sched_lock(); /* ** Found the task being suspended... suspend it. */ if ( current_tcb != self_tcb ) { /* ** Task being suspended is not the current task. */ current_tcb->suspend_reason = WAIT_TSUSP; pthread_kill( current_tcb->pthrid, SIGSTOP ); sched_unlock(); } else { /* ** Suspend the currently executing task's pthread ** if it doesn't have the scheduler locked. */ sched_unlock(); pthread_mutex_lock( &p2pt_sched_lock ); if ( scheduler_locked == pthread_self() ) { pthread_mutex_unlock( &p2pt_sched_lock ); } else { /* ** Suspend the currently executing pthread */ pthread_mutex_unlock( &p2pt_sched_lock ); self_tcb->suspend_reason = WAIT_TSUSP; pthread_kill( self_tcb->pthrid, SIGSTOP ); } } } else { error = ERR_SUSP; } } else error = ERR_OBJDEL; } return( error );}/******************************************************************************* t_resume - resume the specified p2pthread task
*****************************************************************************/ULONG t_resume( ULONG tid ){ p2pthread_cb_t *current_tcb; p2pthread_cb_t *self_tcb; ULONG error; error = ERR_NO_ERROR; sched_lock(); self_tcb = my_tcb(); /* ** Resume the task whose taskid matches tid. ** If the task_list contains tasks, scan it for the tcb ** whose task id matches the one to be resumed. */ current_tcb = tcb_for( tid ); if ( current_tcb != (p2pthread_cb_t *)NULL ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -