📄 ltasklib.c
字号:
** and set the new scheduling priority. */ new_priority = translate_priority( pri, sched_policy, &error ); (tcb->prv_priority).sched_priority = new_priority; pthread_attr_setschedparam( &(tcb->attr), &(tcb->prv_priority) ); /* ** Entry point for task */ tcb->entry_point = funcptr; /* ** Initially assume TCB statically (not dynamically) allocated */ tcb->static_tcb = 1; /* ** Option flags for task */ tcb->flags = opts; /* ** The task is initially 'created' with no pthread running it. */ tcb->state = DEAD; tcb->suspend_list = (v2pthread_cb_t **)NULL; tcb->nxt_susp = (v2pthread_cb_t *)NULL; tcb->nxt_task = (v2pthread_cb_t *)NULL; /* ** Nesting level for number of taskSafe calls */ tcb->delete_safe_count = 0; /* ** Mutex and Condition variable for task delete 'pend' */ pthread_mutex_init( &(tcb->tdelete_lock), (pthread_mutexattr_t *)NULL ); pthread_cond_init( &(tcb->t_deletable), (pthread_condattr_t *)NULL ); /* ** Mutex and Condition variable for task delete 'broadcast' */ pthread_mutex_init( &(tcb->dbcst_lock), (pthread_mutexattr_t *)NULL ); pthread_cond_init( &(tcb->delete_bcplt), (pthread_condattr_t *)NULL ); /* ** First task control block in list of tasks waiting on this task ** (for deletion purposes) */ tcb->first_susp = (v2pthread_cb_t *)NULL; /* ** Save the caller's task arguments in the task control block */ tcb->parms[0] = arg1; tcb->parms[1] = arg2; tcb->parms[2] = arg3; tcb->parms[3] = arg4; tcb->parms[4] = arg5; tcb->parms[5] = arg6; tcb->parms[6] = arg7; tcb->parms[7] = arg8; tcb->parms[8] = arg9; tcb->parms[9] = arg10; /* ** If everything's okay thus far, we have a valid TCB ready to go. */ if ( error == OK ) { /* ** Insert the task control block into the task list. ** First see if the task list contains any tasks yet. */ if ( task_list == (v2pthread_cb_t *)NULL ) { task_list = tcb; } else { /* ** Append the new tcb to the task list. */ for ( current_tcb = task_list; current_tcb->nxt_task != (v2pthread_cb_t *)NULL; current_tcb = current_tcb->nxt_task ); current_tcb->nxt_task = tcb; } } pthread_mutex_unlock( &task_list_lock ); pthread_cleanup_pop( 0 ); } else /* NULL TCB pointer */ { error = S_objLib_OBJ_ID_ERROR; } if ( error != OK ) { errno = (int)error; error = ERROR; } return( error );}/******************************************************************************* taskIsReady - indicates if the specified task is ready to run*****************************************************************************/BOOL taskIsReady( int taskid ){ v2pthread_cb_t *tcb; BOOL result; result = (BOOL)FALSE; pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&task_list_lock ); pthread_mutex_lock( &task_list_lock ); if ( taskid == 0 ) /* ** NULL taskid specifies current task - get TCB for current task */ tcb = my_tcb(); else /* ** Get TCB for task specified by taskid */ tcb = tcb_for( taskid ); if ( tcb != (v2pthread_cb_t *)NULL ) if ( (tcb->state & RDY_MSK) == READY ) result = (BOOL)TRUE; pthread_cleanup_pop( 1 ); return( result );}/******************************************************************************* taskIsSuspended - indicates if the specified task is explicitly suspended *****************************************************************************/BOOL taskIsSuspended( int taskid ){ v2pthread_cb_t *tcb; BOOL result; result = (BOOL)FALSE; pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&task_list_lock ); pthread_mutex_lock( &task_list_lock ); if ( taskid == 0 ) /* ** NULL taskid specifies current task - get TCB for current task */ tcb = my_tcb(); else /* ** Get TCB for task specified by taskid */ tcb = tcb_for( taskid ); if ( tcb != (v2pthread_cb_t *)NULL ) if ( (tcb->state & SUSPEND) == SUSPEND ) result = (BOOL)TRUE; pthread_cleanup_pop( 1 ); return( result );}/******************************************************************************* taskActivate - creates a pthread containing the specified v2pthread task*****************************************************************************/STATUS taskActivate( int tid ){ v2pthread_cb_t *tcb; STATUS error; error = OK; /* ** 'Lock the v2pthread scheduler' to defer any context switch to a higher ** priority task until after this call has completed its work. */ taskLock(); tcb = tcb_for( tid ); if ( tcb != (v2pthread_cb_t *)NULL ) { /* ** Found our task control block. ** Start a new real-time pthread for the task. */ if ( tcb->state == DEAD ) { tcb->state = READY;#ifdef DIAG_PRINTFS printf( "\r\ntaskActivate task @ %p tcb @ %p:", tcb->entry_point, tcb );#endif if ( pthread_create( &(tcb->pthrid), &(tcb->attr), task_wrapper, (void *)tcb ) != 0 ) {#ifdef DIAG_PRINTFS perror( "\r\ntaskActivate pthread_create returned error:" );#endif error = S_memLib_NOT_ENOUGH_MEMORY; tcb_delete( tcb ); } } else { /* ** task already made runnable */#ifdef DIAG_PRINTFS printf( "\r\ntaskActivate task @ tcb %p already active", tcb );#endif } } else error = S_objLib_OBJ_ID_ERROR; /* ** 'Unlock the v2pthread scheduler' to enable a possible context switch ** to a task made runnable by this call. */ taskUnlock(); if ( error != OK ) { errno = (int)error; error = ERROR; } return( error );}/******************************************************************************* taskSpawn - initializes the requisite data structures to support v2pthread ** task behavior not directly supported by Posix threads and** creates a pthread to contain the specified v2pthread task.*****************************************************************************/int taskSpawn( char *name, int pri, int opts, int stksize, int (*funcptr)( int,int,int,int,int,int,int,int,int,int ), int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10 ){ v2pthread_cb_t *tcb; int my_tid; STATUS error; char myname[16]; /* First allocate memory for a new pthread task control block */ tcb = ts_malloc( sizeof( v2pthread_cb_t ) ); if ( tcb != (v2pthread_cb_t *)NULL ) { /* ** Synthesize a default task name if none specified */ my_tid = new_tid(); if ( name == (char *)NULL ) { sprintf( myname, "t%d", my_tid ); name = &(myname[0]); } /* ** Initialize the task control block and pthread attribute structure. */ error = taskInit( tcb, name, pri, opts, (char *)NULL, stksize, funcptr, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 ); if ( error == OK ) { /* ** Establish 'normal' task identifier, overwriting taskid set by ** taskInit call. */ pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&task_list_lock ); pthread_mutex_lock( &task_list_lock ); tcb->taskid = my_tid; /* ** Indicate TCB dynamically allocated */ tcb->static_tcb = 0; pthread_mutex_unlock( &task_list_lock ); pthread_cleanup_pop( 0 ); /* ** Activate (begin execution of) the task just initialized. */ error = taskActivate( my_tid ); } else { /* ** OOPS! Something went wrong... clean up & exit. */ ts_free( (void *)tcb ); } } else /* malloc failed */ { error = S_smObjLib_NOT_INITIALIZED; my_tid = (int)error; } if ( error != OK ) { my_tid = errno = (int)error; } return( my_tid );}/******************************************************************************* taskSuspend - suspends the specified v2pthread task*****************************************************************************/STATUS taskSuspend( int tid ){ v2pthread_cb_t *current_tcb; v2pthread_cb_t *self_tcb; STATUS error; error = OK; self_tcb = my_tcb(); if ( tid == 0 ) { /* ** Suspend currently executing task... get its pthread ID */ if ( self_tcb != (v2pthread_cb_t *)NULL ) { /* ** Don't suspend if currently executing task has the ** scheduler locked! */ pthread_mutex_lock( &v2pthread_task_lock ); if ( scheduler_locked == pthread_self() ) { if ( taskLock_level < 1L ) { /* ** Suspend the currently executing task's pthread */ pthread_mutex_unlock( &v2pthread_task_lock ); self_tcb->state |= SUSPEND; pthread_kill( self_tcb->pthrid, SIGSTOP ); } else pthread_mutex_unlock( &v2pthread_task_lock ); } else { /* ** Suspend the currently executing task's pthread */ pthread_mutex_unlock( &v2pthread_task_lock ); self_tcb->state |= SUSPEND; 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 != (v2pthread_cb_t *)NULL ) { /* ** Suspend task if task not already suspended. */ if ( !(current_tcb->state & SUSPEND) ) { taskLock(); /* ** Found the task being suspended... suspend it. */ if ( current_tcb != self_tcb ) { /* ** Task being suspended is not the current task. */ current_tcb->state |= SUSPEND; pthread_kill( current_tcb->pthrid, SIGSTOP ); taskUnlock(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -