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

📄 sema4.c

📁 linux环境支持psos的操作系统。非常适合进行移植的朋友。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
 * sema4.c - defines the wrapper functions and data structures needed
 *           to implement a Wind River pSOS+ (R) semaphore API 
 *           in a POSIX Threads environment.
 *           to implement a pSOS+ API in a POSIX Threadenvironment.
 ****************************************************************************/

#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <semaphore.h>
#include <sys/time.h>
#include "p2pthread.h"

#undef DIAG_PRINTFS

#define SM_PRIOR     0x02
#define SM_NOWAIT    0x01

#define ERR_TIMEOUT  0x01
#define ERR_NODENO   0x04
#define ERR_OBJDEL   0x05
#define ERR_OBJTFULL 0x08
#define ERR_OBJNF    0x09

#define ERR_NOSCB    0x41
#define ERR_NOSEM    0x42
#define ERR_SKILLD   0x43
#define ERR_TATSDEL  0x44

#define SEND  0
#define KILLD 2

/*****************************************************************************
**  Control block for p2pthread semaphore
**
**  The basic POSIX semaphore does not provide for time-bounded waits nor
**  for selection of a thread to ready based either on FIFO or PRIORITY-based
**  waiting.  This 'wrapper' extends the POSIX pthreads semaphore to include
**  the attributes of a p2pthread semaphore.
**
*****************************************************************************/
typedef struct p2pt_sema4
{
        /*
        ** ID for semaphore
        */
    ULONG
        smid;

        /*
        ** Semaphore Name
        */
    char
        sname[4];

        /*
        ** Option Flags for semaphore
        */
    ULONG
        flags;

        /*
        ** Mutex and Condition variable for semaphore post/pend
        */
    pthread_mutex_t
        sema4_lock;
    pthread_cond_t
        sema4_send;

        /*
        ** Mutex and Condition variable for semaphore delete
        */
    pthread_mutex_t
        smdel_lock;
    pthread_cond_t
        smdel_cplt;

        /*
        **  Pthread semaphore used to maintain count.
        */
    sem_t
        pthread_sema4;

        /*
        ** Type of send operation last performed on semaphore
        */
    int
        send_type;

        /*
        **  Pointer to next semaphore control block in semaphore list.
        */
    struct p2pt_sema4 *
        nxt_sema4;

        /*
        ** First task control block in list of tasks waiting on semaphore
        */
    p2pthread_cb_t *
        first_susp;
} p2pt_sema4_t;

/*****************************************************************************
**  External function and data references
*****************************************************************************/
extern void *
    ts_malloc( size_t blksize );
extern void
    ts_free( void *blkaddr );
extern p2pthread_cb_t *
   my_tcb( void );
extern void
   sched_lock( void );
extern void
   sched_unlock( void );
extern ULONG
   tm_wkafter( ULONG interval );
extern void
   link_susp_tcb( p2pthread_cb_t **list_head, p2pthread_cb_t *new_entry );
extern void
   unlink_susp_tcb( p2pthread_cb_t **list_head, p2pthread_cb_t *entry );
extern int
   signal_for_my_task( p2pthread_cb_t **list_head, int pend_order );

/*****************************************************************************
**  p2pthread Global Data Structures
*****************************************************************************/

/*
**  sema4_list is a linked list of semaphore control blocks.  It is used to locate
**             semaphores by their ID numbers.
*/
static p2pt_sema4_t *
    sema4_list;

/*
**  sema4_list_lock is a mutex used to serialize access to the semaphore list
*/
static pthread_mutex_t
    sema4_list_lock = PTHREAD_MUTEX_INITIALIZER;


/*****************************************************************************
** smcb_for - returns the address of the semaphore control block for the semaphore
**            idenified by smid
*****************************************************************************/
static p2pt_sema4_t *
   smcb_for( ULONG smid )
{
    p2pt_sema4_t *current_smcb;
    int found_smid;

        if ( sema4_list != (p2pt_sema4_t *)NULL )
        {
            /*
            **  One or more semaphores already exist in the semaphore list...
            **  Scan the existing semaphores for a matching ID.
            */
            found_smid = FALSE;
            for ( current_smcb = sema4_list; 
                  current_smcb != (p2pt_sema4_t *)NULL;
                  current_smcb = current_smcb->nxt_sema4 )
            {
                if ( current_smcb->smid == smid )
                {
                    found_smid = TRUE;
                    break;
                }
            }
            if ( found_smid == FALSE )
                /*
                **  No matching ID found
                */
                current_smcb = (p2pt_sema4_t *)NULL;
        }
        else
            current_smcb = (p2pt_sema4_t *)NULL;
 
    return( current_smcb );
}


/*****************************************************************************
** new_smid - automatically returns a valid, unused semaphore ID
*****************************************************************************/
static ULONG
   new_smid( void )
{
    p2pt_sema4_t *current_smcb;
    ULONG new_sema4_id;

    /*
    **  Protect the semaphore list while we examine it.
    */
    pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,
                          (void *)&sema4_list_lock );
    pthread_mutex_lock( &sema4_list_lock );

    /*
    **  Get the highest previously assigned semaphore id and add one.
    */
    if ( sema4_list != (p2pt_sema4_t *)NULL )
    {
        /*
        **  One or more semaphores already exist in the semaphore list...
        **  Find the highest semaphore ID number in the existing list.
        */
        new_sema4_id = sema4_list->smid;
        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 > new_sema4_id )
            {
                new_sema4_id = (current_smcb->nxt_sema4)->smid;
            }
        }

        /*
        **  Add one to the highest existing semaphore ID
        */
        new_sema4_id++;
    }
    else
    {
        /*
        **  this is the first semaphore being added to the semaphore list.
        */
        new_sema4_id = 1;
    }
 
    /*
    **  Re-enable access to the semaphore list by other threads.
    */
    pthread_mutex_unlock( &sema4_list_lock );
    pthread_cleanup_pop( 0 );

    return( new_sema4_id );
}

/*****************************************************************************
** link_smcb - appends a new semaphore control block pointer to the sema4_list
*****************************************************************************/
static void
   link_smcb( p2pt_sema4_t *new_sema4 )
{
    p2pt_sema4_t *current_smcb;

    /*
    **  Protect the semaphore list while we examine and modify it.
    */
    pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,
                          (void *)&sema4_list_lock );
    pthread_mutex_lock( &sema4_list_lock );

    new_sema4->nxt_sema4 = (p2pt_sema4_t *)NULL;
    if ( sema4_list != (p2pt_sema4_t *)NULL )
    {
        /*
        **  One or more semaphores already exist in the semaphore list...
        **  Insert the new entry in ascending numerical sequence by smid.
        */
        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 > new_sema4->smid )
            {
                new_sema4->nxt_sema4 = current_smcb->nxt_sema4;
                break;
            }
        }
        current_smcb->nxt_sema4 = new_sema4;
#ifdef DIAG_PRINTFS 
        printf( "\r\nadd semaphore cb @ %p to list @ %p", new_sema4,
                current_smcb );
#endif
    }
    else
    {
        /*
        **  this is the first semaphore being added to the semaphore list.
        */
        sema4_list = new_sema4;
#ifdef DIAG_PRINTFS 
        printf( "\r\nadd semaphore cb @ %p to list @ %p", new_sema4,
                &sema4_list );
#endif
    }
 
    /*
    **  Re-enable access to the semaphore list by other threads.
    */
    pthread_mutex_unlock( &sema4_list_lock );
    pthread_cleanup_pop( 0 );
}

/*****************************************************************************
** unlink_smcb - removes a semaphore control block pointer from the sema4_list
*****************************************************************************/
static p2pt_sema4_t *
   unlink_smcb( ULONG smid )
{
    p2pt_sema4_t *current_smcb;
    p2pt_sema4_t *selected_smcb;

    selected_smcb =  (p2pt_sema4_t *)NULL;

    if ( sema4_list != (p2pt_sema4_t *)NULL )
    {
        /*
        **  One or more semaphores exist in the semaphore list...
        **  Protect the semaphore list while we examine and modify it.
        */
        pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,
                              (void *)&sema4_list_lock );
        pthread_mutex_lock( &sema4_list_lock );

        /*
        **  Scan the semaphore list for an smcb with a matching semaphore ID
        */
        if ( sema4_list->smid == smid )
        {
            /*
            **  The first semaphore in the list matches the selected ID
            */
            selected_smcb = sema4_list; 
            sema4_list = selected_smcb->nxt_sema4;
#ifdef DIAG_PRINTFS 
            printf( "\r\ndel semaphore cb @ %p from list @ %p", selected_smcb,
                    &sema4_list );

⌨️ 快捷键说明

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