📄 ltasklib.c
字号:
*/ new_entry->suspend_list = list_head; /* ** Update the task state. */ new_entry->state |= PEND; pthread_cleanup_pop( 1 ); }}/******************************************************************************* unlink_susp_tcb - removes tcb pointer from a linked list of tcb pointers** for tasks suspended on the object owning the list.*****************************************************************************/void unlink_susp_tcb( v2pthread_cb_t **list_head, v2pthread_cb_t *entry ){ v2pthread_cb_t *current_tcb; if ( list_head != (v2pthread_cb_t **)NULL ) { pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&task_list_lock ); pthread_mutex_lock( &task_list_lock ); if ( *list_head == entry ) { *list_head = entry->nxt_susp;#ifdef DIAG_PRINTFS printf( "\r\ndel susp_tcb @ %p from list @ %p - newlist head %p", entry, list_head, *list_head );#endif } else { for ( current_tcb = *list_head; current_tcb != (v2pthread_cb_t *)NULL; current_tcb = current_tcb->nxt_susp ) { if ( current_tcb->nxt_susp == entry ) { current_tcb->nxt_susp = entry->nxt_susp;#ifdef DIAG_PRINTFS printf( "\r\ndel susp_tcb @ %p from list @ %p", entry, current_tcb );#endif } } } entry->nxt_susp = (v2pthread_cb_t *)NULL; /* ** Update the task state. */ entry->state &= (!PEND); pthread_cleanup_pop( 1 ); }}/******************************************************************************* signal_for_my_task - searches the specified 'pended task list' for the** task to be selected according to the specified** pend order. If the selected task is the currently** executing task, the task is deleted from the** specified pended task list and returns a non-zero** result... otherwise the pended task list is not** modified and a zero result is returned.*****************************************************************************/int signal_for_my_task( v2pthread_cb_t **list_head, int pend_order ){ v2pthread_cb_t *signalled_task; v2pthread_cb_t *current_tcb; int result; result = FALSE;#ifdef DIAG_PRINTFS printf( "\r\nsignal_for_my_task - list head = %p", *list_head );#endif if ( list_head != (v2pthread_cb_t **)NULL ) { signalled_task = *list_head; /* ** First determine which task is being signalled */ if ( pend_order != 0 ) { /* ** Tasks pend in priority order... locate the highest priority ** task in the pended list. */ for ( current_tcb = *list_head; current_tcb != (v2pthread_cb_t *)NULL; current_tcb = current_tcb->nxt_susp ) { if ( (current_tcb->prv_priority).sched_priority > (signalled_task->prv_priority).sched_priority ) signalled_task = current_tcb;#ifdef DIAG_PRINTFS printf( "\r\nsignal_for_my_task - tcb @ %p priority %d", current_tcb, (current_tcb->prv_priority).sched_priority );#endif } } /* else ** ** Tasks pend in FIFO order... signal is for task at list head. */ /* ** Signalled task located... see if it's the currently executing task. */ if ( signalled_task == my_tcb() ) { /* ** The currently executing task is being signalled... */ result = TRUE; }#ifdef DIAG_PRINTFS printf( "\r\nsignal_for_my_task - signalled tcb @ %p my tcb @ %p", signalled_task, my_tcb() );#endif } return( result );}/******************************************************************************* new_tid - assigns the next unused task ID for the caller's task*****************************************************************************/static int new_tid( void ){ v2pthread_cb_t *current_tcb; int new_taskid; /* ** Get the highest previously assigned task id and add one. */ if ( task_list != (v2pthread_cb_t *)NULL ) { /* ** One or more tasks already exist in the task list... ** Find the highest task ID number in the existing list. */ new_taskid = 0; for ( current_tcb = task_list; current_tcb->nxt_task != (v2pthread_cb_t *)NULL; current_tcb = current_tcb->nxt_task ) { /* ** We use a kluge here to prevent address-based task IDs created ** by explicit taskInit calls from polluting the normal sequence ** for task ID numbers. This is based on the PROBABILITY that ** Linux will not allocate pthread data space below the 64K ** address space. NOTE that this will BREAK taskSpawn if you ** create 64K tasks or more. */ if ( ((current_tcb->nxt_task)->taskid < 65536) && ((current_tcb->nxt_task)->taskid > new_taskid) ) { new_taskid = (current_tcb->nxt_task)->taskid; } } /* ** Add one to the highest existing task ID */ new_taskid++; } else { /* ** this is the first task being added to the task list. */ new_taskid = 1; } return( new_taskid );}/******************************************************************************* translate_priority - translates a v2pthread priority into a pthreads priority*****************************************************************************/static int translate_priority( int v2pthread_priority, int sched_policy, int *errp ){ int max_priority, min_priority, pthread_priority; /* ** Validate the range of the user's task priority. */ if ( (v2pthread_priority > MIN_V2PT_PRIORITY) | (v2pthread_priority < MAX_V2PT_PRIORITY) ) *errp = S_taskLib_ILLEGAL_PRIORITY; /* ** Translate the v2pthread priority into a pthreads priority. ** 'Invert' the caller's priority so highest priority == highest number. */ pthread_priority = MIN_V2PT_PRIORITY - v2pthread_priority; /* ** Next get the allowable priority range for the scheduling policy. */ min_priority = sched_get_priority_min( sched_policy ); max_priority = sched_get_priority_max( sched_policy ); /* ** 'Telescope' the v2pthread priority (0-255) into the smaller pthreads ** priority range (1-97) on a proportional basis. NOTE that this may ** collapse some distinct v2pthread priority levels into the same priority. ** Use this technique if the tasks span a large priority range but no ** tasks are within fewer than 3 levels of one another. pthread_priority *= max_priority; pthread_priority /= (MIN_V2PT_PRIORITY + 1); */ /* ** Now 'clip' the new priority level to within priority range. ** Reserve max_priority level for temporary use during system calls. ** Reserve (max_priority level - 1) for the system exception task. ** NOTE that relative v2pthread priorities may not translate properly ** if the v2pthread priorities used span several multiples of max_priority. ** Use this technique if the tasks span a small priority range and their ** relative priorities are within 3 or fewer levels of one another. */ pthread_priority %= (max_priority - 1); if ( pthread_priority < min_priority ) pthread_priority = min_priority; return( pthread_priority );}/******************************************************************************* tcb_delete - deletes a pthread task control block from the task_list** and frees the memory allocated for the tcb*****************************************************************************/static void tcb_delete( v2pthread_cb_t *tcb ){ v2pthread_cb_t *current_tcb; /* ** If the task_list contains tasks, scan it for a link to the tcb ** being deleted. */ if ( task_list != (v2pthread_cb_t *)NULL ) { /* ** Remove the task from the suspend list for any object it ** is pending on. */#ifdef DIAG_PRINTFS printf( "\r\ntcb_delete - tcb @ %p suspend_list = %p", tcb, tcb->suspend_list ); fflush( stdout );#endif unlink_susp_tcb( tcb->suspend_list, tcb ); pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&task_list_lock ); pthread_mutex_lock( &task_list_lock ); if ( tcb == task_list ) { task_list = tcb->nxt_task; } else { for ( current_tcb = task_list; current_tcb->nxt_task != (v2pthread_cb_t *)NULL; current_tcb = current_tcb->nxt_task ) { if ( tcb == current_tcb->nxt_task ) { /* ** Found the tcb just prior to the one being deleted. ** Unlink the tcb being deleted from the task_list. */#ifdef DIAG_PRINTFS printf( "\r\ntcb_delete - removing tcb @ %p from task list", tcb ); fflush( stdout );#endif current_tcb->nxt_task = tcb->nxt_task; break; } } } pthread_cleanup_pop( 1 ); } /* Release the memory occupied by the tcb being deleted. */ if ( tcb->taskname != (char *)NULL ) { ts_free( (void *)tcb->taskname ); } if ( !(tcb->static_tcb) ) ts_free( (void *)tcb );}/******************************************************************************* notify_task_delete - notifies any pended tasks of the specified task's** deletion.*****************************************************************************/void notify_task_delete( v2pthread_cb_t *tcb ){ /* ** Task just made deletable... ensure that we awaken any ** other tasks pended on deletion of this task ** ** Lock mutex for task delete broadcast completion */#ifdef DIAG_PRINTFS printf( "\r\nnotify_task_delete - lock delete bcast mutex @ tcb %p", tcb );#endif pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&(tcb->dbcst_lock) ); pthread_mutex_lock( &(tcb->dbcst_lock) ); /* ** Lock mutex for deletion condition variable */#ifdef DIAG_PRINTFS printf( "\r\nnotify_task_delete - lock delete cond var mutex @ tcb %p", tcb );#endif pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&(tcb->tdelete_lock)); pthread_mutex_lock( &(tcb->tdelete_lock) ); /* ** Signal the condition variable for task deletion */#ifdef DIAG_PRINTFS printf( "\r\nnotify_task_delete - bcast delete cond variable @ tcb %p", tcb );#endif pthread_cond_broadcast( &(tcb->t_deletable) ); /* ** Unlock the task deleton mutex. */#ifdef DIAG_PRINTFS printf( "\r\nnotify_task_delete - unlock delete cond var mutex @ tcb %p", tcb );#endif pthread_cleanup_pop( 1 ); /* ** Wait for all pended tasks to receive deletion notification. ** The last task to receive the notification will signal the ** delete broadcast-complete condition variable. */#ifdef DIAG_PRINTFS printf( "\r\nnotify_task_delete - wait till pended tasks respond @ tcb %p", tcb );#endif while ( tcb->first_susp != (v2pthread_cb_t *)NULL ) pthread_cond_wait( &(tcb->delete_bcplt), &(tcb->dbcst_lock) );#ifdef DIAG_PRINTFS printf( "\r\nnotify_task_delete - all pended tasks responded @ tcb %p", tcb );#endif /* ** Unlock the task delete broadcast completion mutex. */#ifdef DIAG_PRINTFS printf( "\r\nnotify_task_delete - unlock delete bcast mutex @ tcb %p", tcb );#endif pthread_cleanup_pop( 1 );}/******************************************************************************* taskDeleteForce - removes the specified task(s) from the task list,** frees the memory occupied by the task control block(s),** and kills the pthread(s) associated with the task(s).*****************************************************************************/STATUS taskDeleteForce( int tid ){ v2pthread_cb_t *current_tcb; v2pthread_cb_t *self_tcb; STATUS error; error = OK; taskLock(); /* ** Delete 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 deleted. */ self_tcb = my_tcb(); if ( tid == 0 ) /* ** NULL tid specifies current task - get TCB for current task */ current_tcb = self_tcb; else /* ** Get TCB for task specified by tid */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -