📄 ltasklib.c
字号:
current_tcb = tcb_for( tid ); /* ** Make sure valid TCB found in scan of task list */ if ( current_tcb != (v2pthread_cb_t *)NULL ) { /* ** Found the task being deleted... first ensure that we ** awaken any other tasks pended on deletion of this task */ if ( current_tcb->first_susp != (v2pthread_cb_t *)NULL ) { notify_task_delete( current_tcb ); } /* ** Any tasks pended on deletion of this task have been awakened. ** Proceed with task deletion. */#ifdef DIAG_PRINTFS printf( "\r\ntaskDeleteForce - delete pthread for task @ tcb %p", current_tcb ); fflush( stdout );#endif if ( current_tcb != self_tcb ) { /* ** Task being deleted is not the current task. ** Kill the task pthread and wait for it to die. ** Then de-allocate its data structures. */#ifdef DIAG_PRINTFS printf( "\r\ntaskDeleteForce - other tcb @ %p", current_tcb ); fflush( stdout );#endif pthread_cancel( current_tcb->pthrid ); pthread_join( current_tcb->pthrid, (void **)NULL ); tcb_delete( current_tcb ); } else { /* ** Kill the currently executing task's pthread ** and then de-allocate its data structures. */#ifdef DIAG_PRINTFS printf( "\r\ntaskDeleteForce - self tcb @ %p", current_tcb ); fflush( stdout );#endif pthread_detach( self_tcb->pthrid ); pthread_cleanup_push( (void(*)(void *))tcb_delete, (void *)self_tcb ); pthread_exit( (void *)NULL ); pthread_cleanup_pop( 0 ); } } else /* ** No TCB found in task list for specified tid... must have already ** been deleted. */ error = S_objLib_OBJ_DELETED; taskUnlock(); if ( error != OK ) { errno = (int)error; error = ERROR; } return( error );}/******************************************************************************* cleanup_scheduler_lock ensures that a killed pthread releases the** scheduler lock if it owned it.*****************************************************************************/static void cleanup_scheduler_lock( void *tcb ){ v2pthread_cb_t *mytcb; mytcb = (v2pthread_cb_t *)tcb; pthread_mutex_lock( &v2pthread_task_lock ); if ( scheduler_locked == pthread_self() ) { taskLock_level = 0; scheduler_locked = (pthread_t)NULL; } pthread_mutex_unlock( &v2pthread_task_lock );}/******************************************************************************* task_wrapper is a pthread used to 'contain' a v2pthread task.*****************************************************************************/void * task_wrapper( void *arg ){ v2pthread_cb_t *tcb; /* ** Ensure that errno for this thread is cleared. */ errno = 0; /* ** Make a parameter block pointer from the caller's argument ** Then extract the needed info from the parameter block and ** free its memory before beginning the v2pthread task */ tcb = (v2pthread_cb_t *)arg; /* ** Ensure that this pthread will release the scheduler lock if killed. */ pthread_cleanup_push( cleanup_scheduler_lock, (void *)tcb ); /* ** Call the v2pthread task. Normally this is an endless loop and doesn't ** return here. */#ifdef DIAG_PRINTFS printf( "\r\ntask_wrapper starting task @ %p tcb @ %p:", tcb->entry_point, tcb ); sleep( 1 );#endif (*(tcb->entry_point))( tcb->parms[0], tcb->parms[1], tcb->parms[2], tcb->parms[3], tcb->parms[4], tcb->parms[5], tcb->parms[6], tcb->parms[7], tcb->parms[8], tcb->parms[9] ); /* ** 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 taskDelete takes no action if the task has already been deleted. */ taskDeleteForce( tcb->taskid ); return( (void *)NULL );}/******************************************************************************* taskDelay - suspends the calling task for the specified number of ticks.** ( one tick is currently implemented as ten milliseconds )*****************************************************************************/STATUS taskDelay( int interval ){ struct timeval now, timeout; unsigned long usec; v2pthread_cb_t *tcb; /* ** Calculate timeout delay in seconds and microseconds */ usec = (unsigned long)(interval * V2PT_TICK * 1000); /* ** Update the task state. */ tcb = my_tcb(); tcb->state |= DELAY; /* ** Delay of zero means yield CPU to other tasks of same priority */ if ( usec > 0L ) { /* ** Establish absolute time at expiration of delay interval */ gettimeofday( &now, (struct timezone *)NULL ); timeout.tv_sec = now.tv_sec; timeout.tv_usec = now.tv_usec; timeout.tv_usec += usec; if ( timeout.tv_usec > 1000000 ) { timeout.tv_sec += timeout.tv_usec / 1000000; timeout.tv_usec = timeout.tv_usec % 1000000; } /* ** Wait for the current time of day to reach the time of day calculated ** after the timeout expires. The loop is necessary since the thread ** may be awakened by signals before the timeout has elapsed. */ while ( usec > 0 ) { /* ** Add a cancellation point to this loop, ** since there are no others. */ pthread_testcancel(); usleep( usec ); gettimeofday( &now, (struct timezone *)NULL ); if ( timeout.tv_usec > now.tv_usec ) { usec = timeout.tv_usec - now.tv_usec; if ( timeout.tv_sec < now.tv_sec ) usec = 0; else usec += ((timeout.tv_sec - now.tv_sec) * 1000000); } else { usec = (timeout.tv_usec + 1000000) - now.tv_usec; if ( (timeout.tv_sec - 1) < now.tv_sec ) usec = 0; else usec += (((timeout.tv_sec - 1) - now.tv_sec) * 1000000); } } } else /* ** Yield to any other task of same priority without blocking. */ sched_yield(); /* ** Update the task state. */ tcb->state &= (!DELAY); return( OK );}/******************************************************************************* taskIdListGet - returns a list of active task identifiers*****************************************************************************/int taskIdListGet( int list[], int maxIds ){ v2pthread_cb_t *current_tcb; int count; count = 0; /* ** 'Lock the v2pthread scheduler' */ taskLock(); if ( (task_list != (v2pthread_cb_t *)NULL) && (list != (int *)NULL) ) { /* ** One or more tasks already exist in the task list... ** Return the identifiers for the first (maxIds) tasks in the list. ** Quit when (a) the end of the task list is reached or (b) the ** specified capacity of the caller's ID list is reached. */ for ( current_tcb = task_list; current_tcb != (v2pthread_cb_t *)NULL; current_tcb = current_tcb->nxt_task ) { if ( count < maxIds ) { list[count] = current_tcb->taskid; count++; } } } /* ** 'Unlock the v2pthread scheduler' */ taskUnlock(); return( count );}/******************************************************************************* taskIdSelf - returns the identifier of the calling task*****************************************************************************/int taskIdSelf( void ){ v2pthread_cb_t *self_tcb; int my_tid; pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&task_list_lock ); pthread_mutex_lock( &task_list_lock ); self_tcb = my_tcb(); pthread_cleanup_pop( 1 ); if ( self_tcb != (v2pthread_cb_t *)NULL ) my_tid = self_tcb->taskid; else my_tid = 0; return( my_tid );}/******************************************************************************* taskIdVerify - indicates whether the specified task exists or not*****************************************************************************/STATUS taskIdVerify( int taskid ){ v2pthread_cb_t *tcb; STATUS error; 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 ); pthread_cleanup_pop( 1 ); if ( tcb != (v2pthread_cb_t *)NULL ) error = OK; else /* NULL TCB pointer */ error = S_objLib_OBJ_ID_ERROR; if ( error != OK ) { errno = (int)error; error = ERROR; } return( error );}/******************************************************************************* taskInit - initializes the requisite data structures to support v2pthread ** task behavior not directly supported by Posix threads.*****************************************************************************/STATUS taskInit( v2pthread_cb_t *tcb, char *name, int pri, int opts, char *pstack, 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 *current_tcb; int i, new_priority, sched_policy; STATUS error; error = OK; if ( tcb != (v2pthread_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; /* ** Use TCB address as task identifier */ tcb->taskid = (int)tcb; /* ** Copy the task name (if any) */ if ( name != (char *)NULL ) { i = strlen( name ) + 1; tcb->taskname = ts_malloc( i ); if ( tcb->taskname != (char *)NULL ) strncpy( tcb->taskname, name, i ); } else tcb->taskname = (char *)NULL; /* ** Task v2pthread priority level */ tcb->vxw_priority = pri; /* ** 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) ); /* ** Determine whether round-robin time-slicing is to be used or not */ if ( roundRobinIsEnabled() ) sched_policy = SCHED_RR; else sched_policy = SCHED_FIFO; pthread_attr_setschedpolicy( &(tcb->attr), sched_policy ); /* ** Translate the v2pthread priority into a pthreads priority
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -