⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 task.c

📁 linux环境支持psos的操作系统。非常适合进行移植的朋友。
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef DIAG_PRINTFS             printf( "\r\nadd susp_tcb @ %p to list @ %p", new_entry,                    list_head );#endif        }        /*        **  Initialize the suspended task's pointer back to suspend list        **  This is used for cleanup during task deletion by t_delete().        */        new_entry->suspend_list = list_head;        pthread_mutex_unlock( &task_list_lock );        pthread_cleanup_pop( 0 );    }}/******************************************************************************* 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( p2pthread_cb_t **list_head, p2pthread_cb_t *entry ){    p2pthread_cb_t *current_tcb;    if ( list_head != (p2pthread_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 != (p2pthread_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 = (p2pthread_cb_t *)NULL;        pthread_mutex_unlock( &task_list_lock );        pthread_cleanup_pop( 0 );    }}/******************************************************************************* 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( p2pthread_cb_t **list_head, int pend_order ){    p2pthread_cb_t *signalled_task;    p2pthread_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 != (p2pthread_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 != (p2pthread_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 ULONG   new_tid( void ){    p2pthread_cb_t *current_tcb;    ULONG new_taskid;    
	/*
	**  Note: since we only read the task_list, so no locking of 
	**  task_list_lock is needed, and you can't only go to the 
	**  last member in task_list to get it's task_id and plus 1.
	*/
    /*    **  Get the highest previously assigned task id and add one.    */    if ( task_list != (p2pthread_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 = task_list->taskid;        for ( current_tcb = task_list;               current_tcb->nxt_task != (p2pthread_cb_t *)NULL;              current_tcb = current_tcb->nxt_task )        {            if ( (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 p2pthread priority into a pthreads priority*****************************************************************************/static int   translate_priority( ULONG p2pt_priority, int sched_policy, ULONG *errp ){    int max_priority, min_priority, pthread_priority;    /*    **  Validate the range of the user's task priority.    */    if ( (p2pt_priority < MIN_P2PT_PRIORITY) |          (p2pt_priority > MAX_P2PT_PRIORITY) )        *errp = ERR_PRIOR;     /*    **  Translate the p2pthread priority into a pthreads priority.    */    pthread_priority = (int)p2pt_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 );    /*    **  Now 'clip' the new priority level to within priority range.    **  Reserve max_priority level for temporary use during system calls.    **  NOTE that relative p2pthread priorities may not translate properly    **  if the p2pthread priorities used span several multiples of max_priority.    */    pthread_priority %= max_priority;    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( p2pthread_cb_t *tcb ){    p2pthread_cb_t *current_tcb;    /*    **  If the task_list contains tasks, scan it for a link to the tcb    **  being deleted.    */    if ( task_list != (p2pthread_cb_t *)NULL )    {        /*        **  Remove the task from the suspend list for any object it        **  is pending on.        */        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 != (p2pthread_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.                    */                    current_tcb->nxt_task = tcb->nxt_task;                    break;                }            }        }        pthread_mutex_unlock( &task_list_lock );        pthread_cleanup_pop( 0 );    }    /* Release the memory occupied by the tcb being deleted. */    ts_free( (void *)tcb );}/******************************************************************************* t_delete - 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).*****************************************************************************/ULONG   t_delete( ULONG tid ){    p2pthread_cb_t *current_tcb;    p2pthread_cb_t *self_tcb;    ULONG error;    error = ERR_NO_ERROR;    sched_lock();    self_tcb = my_tcb();    if ( tid == 0 )    {        /*        **  Delete currently executing task... get its pthread ID        */        if ( self_tcb != (p2pthread_cb_t *)NULL )        {            /*            **  Kill the currently executing task's pthread and             **  then de-allocate its data structures.            */

			/*	POSIX threads can exist in either the ‘joinable’ state 
			**  or the ‘detached’ state. A given pthread or process 
			**  can wait for a joinable pthread to terminate. At this time,
			**  the process or pthread waiting on the terminating pthread 
			**  obtains an exit status from the pthread and then the terminating 
			**  pthread’s resources are released. A ‘detached’pthread has 
			**  effectively been told that no other process or pthread cares when 
			**  it terminates. This means that when the ‘detached’ pthread 
			**  terminates, its resources are released immediately and no other 
			**  process or pthread can receive termination notice or an exit status. 
			**  If the pthread is deleting itself it must be ‘detached’ in order 
			**  to free its Linux resources upon termination.
			*/              pthread_detach( self_tcb->pthrid );            pthread_cleanup_push( (void(*)(void *))tcb_delete,                                  (void *)self_tcb );            pthread_exit( ( void *)NULL );
			/*
			**  Because pthread_exit is also a termination point func,
			**  so the arg of pthread_cleanup_pop is 0, and it's still
			**  that the function tcb_delete() will be called.
			*/            pthread_cleanup_pop( 0 );        }        else            error = ERR_OBJDEL;    }    else    {        /*        **  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.        */        current_tcb = tcb_for( tid );        if ( current_tcb != (p2pthread_cb_t *)NULL )        {            /*            **  Found the task being deleted... delete it.            */            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.                */                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.                */                pthread_detach( self_tcb->pthrid );                pthread_cleanup_push( (void(*)(void *))tcb_delete,                                      (void *)self_tcb );                pthread_exit( ( void *)NULL );                pthread_cleanup_pop( 0 );            }        }        else            error = ERR_OBJDEL;    }     sched_unlock();    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 ){    p2pthread_cb_t *mytcb;    mytcb = (p2pthread_cb_t *)tcb;    pthread_mutex_lock( &p2pt_sched_lock );    if ( scheduler_locked == pthread_self() )    {        sched_lock_level = 0;        scheduler_locked = (pthread_t)NULL;    }    pthread_mutex_unlock( &p2pt_sched_lock );}/*******************************************************************************  task_wrapper is a pthread used to 'contain' a p2pthread task.*****************************************************************************/static void *    task_wrapper( void *arg ){    p2pthread_cb_t *tcb;    p2pthread_pb_t *parmblk;    void (*task_ptr)( ULONG, ULONG, ULONG, ULONG );        /*    **  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 p2pthread task    */    parmblk = (p2pthread_pb_t *)arg;    tcb = parmblk->tcb;    task_ptr = parmblk->task_ptr;    /*    **  Note: ensure that this pthread will release the scheduler lock if killed.    */    pthread_cleanup_push( cleanup_scheduler_lock, (void *)tcb );    /*    **  Call the p2pthread task.  Normally this is an endless loop and doesn't    **  return here.    */#ifdef DIAG_PRINTFS     printf( "\r\ntask_wrapper starting task @ %p tcb @ %p:", task_ptr, tcb );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -