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

📄 memblk.c

📁 linux环境支持psos的操作系统。非常适合进行移植的朋友。
💻 C
📖 第 1 页 / 共 2 页
字号:
*****************************************************************************/
ULONG
    pt_create( char name[4], void *paddr, void *laddr, ULONG length,
               ULONG bsize, ULONG flags, ULONG *ptid, ULONG *nbuf )
{
    p2pt_prtn_t *prtn;
    ULONG error;
    int i;

    error = ERR_NO_ERROR;

    /*
    **  First allocate memory for the partition control block.
    */
    prtn = (p2pt_prtn_t *)ts_malloc( sizeof( p2pt_prtn_t ) );
    if ( prtn != (p2pt_prtn_t *)NULL )
    {
        /*
        **  Ok... got a control block.
        **  Prepare to allocate and init the first partition data extent.
        */

        /*
        ** Total number of used data blocks in partition
        */
        prtn->used_blk_count = 0L;

        /*
        **  Pointer to data extent for partition
        */
        prtn->data_extent = (prtn_extent_t *)NULL;

        /*
        ** Total data blocks per memory allocation block (extent)
        */
        if ( (bsize % 2) || (bsize < 4) )
            error = ERR_BUFSIZE;
        prtn->blk_size = bsize;

        if ( new_extent_for( prtn, paddr, (length / bsize) ) !=
             (prtn_extent_t *)NULL )
        {
            /*
            ** ID for partition
            */
            prtn->prtn_id = new_prtn_id();
            
            /*
            **  Name for partition
            */
            for ( i = 0; i < 4; i++ )
                prtn->ptname[i] = name[i];

            /*
            ** Option Flags for partition
            */
            prtn->flags = flags;

            /*
            ** Mutex for partition get/release block
            */
            pthread_mutex_init( &(prtn->prtn_lock),
                                (pthread_mutexattr_t *)NULL );
            /*
            **  If no errors thus far, we have a new partition ready to link
            **  into the partition list.
            */
            if ( error == ERR_NO_ERROR )
            {
			    /*
				**  Partition is linked by the acsending sequence of prtn_id. 
				*/
                link_pcb( prtn );

                /*
                **  Return the partition ID into the caller's storage location.
                */
                if ( ptid != (ULONG *)NULL )
                    *ptid = prtn->prtn_id;

                /*
                **  Return the number of buffers in the partition into
                **  the caller's storage location.
                */
                if ( nbuf != (ULONG *)NULL )
                    *nbuf = prtn->free_blk_count;
            }
            else
            {
                /*
                **  Oops!  Problem somewhere above.  Release control block
                **  and data memory and return.
                */
                ts_free( (void *)prtn->data_extent );
                ts_free( (void *)prtn );
            }
        }
        else
        {
            /*
            **  No memory for partition data... free partition control block
            */
            ts_free( (void *)prtn );
            error = ERR_OBJTFULL;
        }
    }
    else
    {
        error = ERR_OBJTFULL;
    }

    return( error );
}

/*****************************************************************************
** delete_prtn - takes care of destroying the specified partition and freeing
**                any resources allocated for that partition
*****************************************************************************/
static void
   delete_prtn( p2pt_prtn_t *prtn )
{
    /*
    **  First remove the partition from the partition list
    */
    unlink_pcb( prtn->prtn_id );

    /*
    **  Next delete the extent control block allocated for partition data.
    */
    ts_free( (void *)prtn->data_extent );

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

}

/*****************************************************************************
** pt_delete - removes the specified partition from the partition list and
**             frees the memory allocated for the partition control block
**             and extents.
*****************************************************************************/
ULONG
    pt_delete( ULONG ptid )
{
    p2pt_prtn_t *prtn;
    ULONG error;

    error = ERR_NO_ERROR;

    if ( (prtn = pcb_for( ptid )) != (p2pt_prtn_t *)NULL )
    {

        /*
        ** Lock mutex for partition delete
        */
        pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,
                              (void *)&(prtn->prtn_lock));
        pthread_mutex_lock( &(prtn->prtn_lock) );

        if ( prtn->flags & PT_DEL )
        {
            /*
            **  Delete the partition even if buffers still allocated from it.
            */
			/*
			**  Note: here we should not use pthread_mutex_unlock(&(prtn->prtn_lock))
			**  to unlock the mutex, cause delete_prtn has do it.
			*/
            sched_lock();
            delete_prtn( prtn );
            sched_unlock();
        }
        else
        {
            /*
            **  Ensure that none of the partition's buffers are allocated.
            */
            sched_lock();
            if ( prtn->used_blk_count > 0L ) 
            {
                error = ERR_BUFINUSE;

                /*
                **  Unlock the mutex for the condition variable
                */
                pthread_mutex_unlock( &(prtn->prtn_lock) );
            }
            else
            {
                /*
                **  No buffers are allocated from the partition. Delete it.
                */
                error = ERR_NO_ERROR;
                delete_prtn( prtn );
            }
            sched_unlock();
        }

        pthread_cleanup_pop( 0 );
    }
    else
    {
        error = ERR_OBJDEL;
    }

    return( error );
}

/*****************************************************************************
** pt_getbuf - obtains a free data buffer from the specified memory partition
*****************************************************************************/
ULONG
    pt_getbuf( ULONG ptid, void **bufaddr )
{
    p2pt_prtn_t *prtn;
    char *blk_ptr;
    ULONG error;

    error = ERR_NO_ERROR;

    if ( (prtn = pcb_for( ptid )) != (p2pt_prtn_t *)NULL )
    {
        /*
        ** Lock mutex for partition block allocation
        */
        pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,
                              (void *)&(prtn->prtn_lock));
        pthread_mutex_lock( &(prtn->prtn_lock) );

        /*
        **  Each free data block contains a pointer to the next free data
        **  block in the partition.  This pointer is a pointer to a char
        **  as well as a pointer to a pointer to a char, since it is the
        **  address of both the next block and the next link pointer.
        **  The caller wants the address of a data block, so cast the
        **  first_free pointer to point to the first free data block
        **  and give that block to the caller.  NOTE that if the free list
        **  is empty, blk_ptr will be returned as a NULL pointer.
        */
        blk_ptr = (char *)prtn->first_free;

        if ( blk_ptr != (char *)NULL )
        {
            /*
            **  Take the contents of the first free data block and interpret
            **  its first bytes as the address of the link pointer in the
            **  following data block.  This address becomes the new value for
            **  the first_free pointer for the partition.  This means data
            **  blocks are always allocated from the front of the free list.
            */
            prtn->first_free = *((char ***)blk_ptr);

            /*
            **  Adjust the block counters to reflect the fact that another
            **  block was just allocated.
            */
            prtn->free_blk_count--;
            prtn->used_blk_count++;
#ifdef DIAG_PRINTFS 
            printf( "\r\npt_getbuf allocated block @ %p from partition %ld nxt_blk @ %p",
                    blk_ptr, ptid, *((char **)blk_ptr) );
#endif
        }
        else
        {
            error = ERR_NOBUF;
#ifdef DIAG_PRINTFS 
            printf( "\r\npt_getbuf - no blocks free in partition %ld", ptid );
#endif
        }

        /*
        **  Unlock the mutex for the condition variable and clean up.
        */
        pthread_mutex_unlock( &(prtn->prtn_lock) );
        pthread_cleanup_pop( 0 );
    }
    else
    {
        blk_ptr = (char *)NULL;
        error = ERR_OBJDEL;       /* Invalid prtn specified */
#ifdef DIAG_PRINTFS 
            printf( "\r\npt_getbuf - partition %ld not found", ptid );
#endif
    }

    /*
    **  Return the allocated block address (or NULL) to the caller's
    **  storage location.
    */
    if ( bufaddr != (void **)NULL )
        *bufaddr = (void *)blk_ptr;

    return( error );
}

/*****************************************************************************
** pt_retbuf - releases a data buffer back to the specified memory partition
*****************************************************************************/
ULONG
    pt_retbuf( ULONG ptid, void *bufaddr )
{
    p2pt_prtn_t *prtn;
    prtn_extent_t *extent;
    unsigned long extent_size;
    char *blk_ptr;
    ULONG error;

    error = ERR_NO_ERROR;

    if ( (prtn = pcb_for( ptid )) != (p2pt_prtn_t *)NULL )
    {

        /*
        **  Ensure that the block being returned falls within this
        **  partition's data memory range.
        */
        blk_ptr = (char *)bufaddr;
        extent = prtn->data_extent;
        extent_size = extent->bcount * prtn->blk_size;
#ifdef DIAG_PRINTFS 
        printf( "\r\npt_retbuf bufaddr @ %p extent base @ %p size %lx",
                blk_ptr, extent->baddr, extent_size );
#endif
        if ( (blk_ptr == extent->baddr) ||
             ((blk_ptr > extent->baddr) && 
              (blk_ptr < (extent->baddr + extent_size))) )
        {
            /*
            ** Lock mutex for partition block release
            */
            pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,
                                  (void *)&(prtn->prtn_lock));
            pthread_mutex_lock( &(prtn->prtn_lock) );

            /*
            **  Search the partition's free list to see if the caller's
            **  buffer has already been freed.
            */
            for ( blk_ptr = (char *)prtn->first_free;
                  blk_ptr != (char *)NULL;
                  blk_ptr = *(char **)blk_ptr )
            {
#ifdef DIAG_PRINTFS 
                printf( "\r\npt_retbuf cur_blk @ %p nxt_blk @ %p",
                        blk_ptr, *(char **)blk_ptr );
#endif
                if ( blk_ptr == (char *)bufaddr )
                {
                    error = ERR_BUFFREE;
                    break;
                }
            }

            if ( error == ERR_NO_ERROR )
            {
                /*
                **  The caller's buffer address falls within the partition
                **  and has not already been freed...
                **  Insert a list-terminating NULL pointer into the block 
                **  being freed up.  Then link the block into the free list
                **  after the previous last free block.  This means free blocks
                **  are always returned to the rear of the free list, ensuring
                **  an even distribution of use for the blocks in the partition.
                */
                blk_ptr = (char *)bufaddr;
                *(char **)blk_ptr = (char *)NULL;
                *(prtn->last_free) = blk_ptr;
                prtn->last_free = (char **)blk_ptr;
                if ( prtn->first_free == (char **)NULL )
                    prtn->first_free = (char **)blk_ptr;

#ifdef DIAG_PRINTFS 
                printf( "\r\npt_retbuf returned block @ %p to partition %ld",
                        blk_ptr, ptid );
#endif

                /*
                **  Adjust the block counters to reflect the fact that another
                **  block was just released.
                */
                prtn->free_blk_count++;
                prtn->used_blk_count--;
            }
#ifdef DIAG_PRINTFS 
            else
            {
                printf( "\r\npt_retbuf - block @ %p already freed", blk_ptr );
            }
#endif
            /*
            **  Unlock the mutex for the condition variable and clean up.
            */
            pthread_mutex_unlock( &(prtn->prtn_lock) );
            pthread_cleanup_pop( 0 );
        }
        else
        {
            error = ERR_BUFADDR;
#ifdef DIAG_PRINTFS 
            printf( "\r\npt_retbuf - block @ %p not in partition %ld",
                    blk_ptr, ptid );
#endif
        }
    }
    else
    {
        error = ERR_OBJDEL;       /* Invalid prtn specified */
    }

    return( error );
}

/*****************************************************************************
** pt_ident - identifies the named p2pthread partition
*****************************************************************************/
ULONG
    pt_ident( char name[4], ULONG node, ULONG *ptid )
{
    p2pt_prtn_t *current_pcb;
    ULONG error;

    error = ERR_NO_ERROR;

    /*
    **  Validate the node specifier... only zero is allowed here.
    */ 
    if ( node != 0L )
        error = ERR_NODENO;
    else
    {
        /*
        **  If queue name string is a NULL pointer, return with error.
        **  We'll ASSUME the ptid pointer isn't NULL!
        */
        if ( name == (char *)NULL )
        {
            *ptid = (ULONG)NULL;
            error = ERR_OBJNF;
        }
        else
        {
            /*
            **  Scan the task list for a name matching the caller's name.
            */
            for ( current_pcb = prtn_list;
                  current_pcb != (p2pt_prtn_t *)NULL;
                  current_pcb = current_pcb->nxt_prtn )
            {
                if ( (strncmp( name, current_pcb->ptname, 4 )) == 0 )
                {
                    /*
                    **  A matching name was found... return its QID
                    */
                    *ptid = current_pcb->prtn_id;
                    break;
                }
            }
            if ( current_pcb == (p2pt_prtn_t *)NULL )
            {
                /*
                **  No matching name found... return caller's QID with error.
                */
                *ptid = (ULONG)NULL;
                error = ERR_OBJNF;
            }
        }
    }

    return( error );
}

⌨️ 快捷键说明

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