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

📄 sema4.c

📁 linux环境支持psos的操作系统。非常适合进行移植的朋友。
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif
        }
        else
        {
            /*
            **  Scan the next smcb for a matching smid while retaining a
            **  pointer to the current smcb.  If the next smcb matches,
            **  select it and then unlink it from the semaphore list.
            */
            for ( current_smcb = sema4_list; 
                  current_smcb->nxt_sema4 != (p2pt_sema4_t *)NULL;
                  current_smcb = current_smcb->nxt_sema4 )
            {
                if ( (current_smcb->nxt_sema4)->smid == smid )
                {
                    /*
                    **  Semaphore ID of next smcb matches...
                    **  Select the smcb and then unlink it by linking
                    **  the selected smcb's next smcb into the current smcb.
                    */
                    selected_smcb = current_smcb->nxt_sema4;
                    current_smcb->nxt_sema4 = selected_smcb->nxt_sema4;
#ifdef DIAG_PRINTFS 
                    printf( "\r\ndel semaphore cb @ %p from list @ %p",
                            selected_smcb, current_smcb );
#endif
                    break;
                }
            }
        }

        /*
        **  Re-enable access to the semaphore list by other threads.
        */
        pthread_mutex_unlock( &sema4_list_lock );
        pthread_cleanup_pop( 0 );
    }

    return( selected_smcb );
}

/*****************************************************************************
** sm_create - creates a p2pthread message semaphore
*****************************************************************************/
ULONG
    sm_create( char name[4], ULONG count, ULONG opt, ULONG *smid )
{
    p2pt_sema4_t *semaphore;
    ULONG error;
    int i;
    char create_error[80];

    error = ERR_NO_ERROR;

    /*
    **  First allocate memory for the semaphore control block
    */
    semaphore = (p2pt_sema4_t *)ts_malloc( sizeof( p2pt_sema4_t ) );
    if ( semaphore != (p2pt_sema4_t *)NULL )
    {
        /*
        **  Ok... got a control block.  Initialize it.
        */

        /*
        ** Option Flags for semaphore
        */
        semaphore->flags = opt;

        /*
        ** ID for semaphore
        */
        semaphore->smid = new_smid();
        if ( smid != (ULONG *)NULL )
            *smid = semaphore->smid;

        /*
        **  Name for semaphore
        */
        for ( i = 0; i < 4; i++ )
            semaphore->sname[i] = name[i];

#ifdef DIAG_PRINTFS 
        printf( "\r\nCreating semaphore %c%c%c%c id %ld @ %p",
                     semaphore->sname[0], semaphore->sname[1],
                     semaphore->sname[r20], semaphore->sname[3],
                     semaphore->smid, semaphore );
#endif

        /*
        ** Mutex and Condition variable for semaphore send/pend
        */
        pthread_mutex_init( &(semaphore->sema4_lock),
                            (pthread_mutexattr_t *)NULL );
        pthread_cond_init( &(semaphore->sema4_send),
                           (pthread_condattr_t *)NULL );

        /*
        ** Mutex and Condition variable for semaphore delete/delete
        */
        pthread_mutex_init( &(semaphore->smdel_lock),
                            (pthread_mutexattr_t *)NULL );
        pthread_cond_init( &(semaphore->smdel_cplt),
                           (pthread_condattr_t *)NULL );

        /*
        **  Pthread semaphore used to maintain count. Cause Linuxthread
		**  didn't inplement the multi-thread shared sema4, so the arg
		**  'pshared' should be set to zero, any other value cause the 
		**  function return with -1.
        */
        if ( sem_init( &(semaphore->pthread_sema4), 0, (unsigned int)count ) )
        {
            sprintf( create_error,
                     "\r\nSemaphore %c%c%c%c creation returned error:",
                     semaphore->sname[0], semaphore->sname[1],
                     semaphore->sname[2], semaphore->sname[3] );
            perror( create_error );
        }

        /*
        ** Type of send operation last performed on semaphore
        */
        semaphore->send_type = SEND;

        /*
        ** First task control block in list of tasks waiting on semaphore
        */
        semaphore->first_susp = (p2pthread_cb_t *)NULL;

        /*
        **  Link the new semaphore into the semaphore list.
        */
        link_smcb( semaphore );
    }
    else
    {
        error = ERR_NOSCB;
    }

    return( error );
}

/*****************************************************************************
** sm_v - releases a p2pthread semaphore token and awakens the first selected
**        task waiting on the semaphore.
*****************************************************************************/
ULONG
   sm_v( ULONG smid )
{
#ifdef DIAG_PRINTFS 
    p2pthread_cb_t *our_tcb;
#endif
    p2pt_sema4_t *semaphore;
    ULONG error;

    error = ERR_NO_ERROR;

    if ( (semaphore = smcb_for( smid )) != (p2pt_sema4_t *)NULL )
    {
#ifdef DIAG_PRINTFS 
        our_tcb = my_tcb();
        printf( "\r\ntask @ %p post to semaphore list @ %p", our_tcb,
                &(semaphore->first_susp) );
#endif

        /*
        **  'Lock the p2pthread scheduler' to defer any context switch to a
        **  higher priority task until after this call has completed its work.
        */
        sched_lock();

        /*
        ** Lock mutex for semaphore send
        */
        pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,
                              (void *)&(semaphore->sema4_lock));
        pthread_mutex_lock( &(semaphore->sema4_lock) );

        sem_post( &(semaphore->pthread_sema4) );

        if ( semaphore->first_susp != (p2pthread_cb_t *)NULL )
            /*
            **  Signal the condition variable for the semaphore
            */
            pthread_cond_broadcast( &(semaphore->sema4_send) );

        /*
        **  Unlock the semaphore mutex. 
        */
        pthread_mutex_unlock( &(semaphore->sema4_lock) );
        pthread_cleanup_pop( 0 );

        /*
        **  'Unlock the p2pthread scheduler' to enable a possible context switch
        **  to a task made runnable by this call.
        */
        sched_unlock();
    }
    else
    {
        error = ERR_OBJDEL;
    }

    return( error );
}

/*****************************************************************************
** delete_sema4 - takes care of destroying the specified semaphore and freeing
**                any resources allocated for that semaphore
*****************************************************************************/
static void
   delete_sema4( p2pt_sema4_t *semaphore )
{
    /*
    **  First remove the semaphore from the semaphore list
    */
    unlink_smcb( semaphore->smid );

    /*
    **  Next destroy the pthreads semaphore
    */
    sem_destroy( &(semaphore->pthread_sema4) );

    /*
    **  Finally delete the semaphore control block itself;
    */
    ts_free( (void *)semaphore );

}

/*****************************************************************************
** sm_delete - removes the specified semaphore from the semaphore list and frees
**              the memory allocated for the semaphore control block and extents.
*****************************************************************************/
ULONG
   sm_delete( ULONG smid )
{
    p2pt_sema4_t *semaphore;
    ULONG error;

    error = ERR_NO_ERROR;

    if ( (semaphore = smcb_for( smid )) != (p2pt_sema4_t *)NULL )
    {
        /*
        **  Send signal and block while any tasks are still waiting
        **  on the semaphore
        */
        sched_lock();
        if ( semaphore->first_susp != (p2pthread_cb_t *)NULL )
        {
            /*
            ** Lock mutex for semaphore delete completion
            */
            pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,
                                  (void *)&(semaphore->smdel_lock) );
            pthread_mutex_lock( &(semaphore->smdel_lock) );

            /*
            ** Lock mutex for semaphore delete
            */
            pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,
                                  (void *)&(semaphore->sema4_lock));
            pthread_mutex_lock( &(semaphore->sema4_lock) );

            /*
            **  Declare the send type
            */
            semaphore->send_type = KILLD;

            error = ERR_TATSDEL;

            /*
            **  Signal the condition variable for the semaphore
            */
            pthread_cond_broadcast( &(semaphore->sema4_send) );

            /*
            **  Unlock the semaphore mutex. 
            */
            pthread_mutex_unlock( &(semaphore->sema4_lock) );
            pthread_cleanup_pop( 0 );

            /*
            **  Wait for all pended tasks to receive delete message.
            **  The last task to receive the message will signal the
            **  delete-complete condition variable.
            */
            while ( semaphore->first_susp != (p2pthread_cb_t *)NULL )
                pthread_cond_wait( &(semaphore->smdel_cplt),
                                   &(semaphore->smdel_lock) );

            /*
            **  Unlock the semaphore delete completion mutex. 
            */
            pthread_mutex_unlock( &(semaphore->smdel_lock) );
            pthread_cleanup_pop( 0 );
        }
        delete_sema4( semaphore );
        sched_unlock();
    }
    else
    {
        error = ERR_OBJDEL;
    }

    return( error );
}

/*****************************************************************************
** waiting_on_sema4 - returns a nonzero result unless a qualifying event
**                    occurs on the specified semaphore which should cause the
**                    pended task to be awakened.  The qualifying events
**                    are:
**                        (1) a message is sent to the semaphore and the current
**                            task is selected to receive it
**                        (2) a delete message is sent to the semaphore
**                        (3) the semaphore is deleted
*****************************************************************************/
static int
    waiting_on_sema4( p2pt_sema4_t *semaphore, struct timespec *timeout,
                      int *retcode )
{
    int result;
    struct timeval now;
    ULONG usec;

    if ( semaphore->send_type & KILLD )
    {
        /*
        **  Semaphore has been killed... waiting is over.
        */
        result = 0;
        *retcode = 0;

⌨️ 快捷键说明

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