硬件锁,c语言实现多生产者多消费者链表

list.c:

///
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

//
// 链表节点
typedef struct node
{
    struct node *next;
    void *data_ptr;
}listnode;

// 链表头
typedef struct head
{
    listnode *head;
    listnode *end;

    int size;
    int state;
    struct node first;
} listhead;

//
// 往链表里增加节点
static int list_add( listhead *list, void *data )
{
    int ret = 0;
    volatile listnode *last = 0;
    volatile listnode *prev = 0;
    listnode *node = (listnode*)malloc(sizeof(listnode));
    if ( node == 0 )
    {
        return -1;
    }

    // last = list->end;
    // list->end = node;
    // last->data_ptr = data;
    do 
    {
        last = list->end;
#if 1
        __asm__ __volatile__ 
        (
		    // 该指令在cpu 486之后支持
            "lock; cmpxchgl %k1, %2"
            : "=a" (prev) // result, %0
            : "r" (node), // new value
              "m" (list->end), // old value
              "0" (last) // %eax
            : "memory"
        );
#else 
		// gcc 4.1以后的版本支持
        ret = __sync_bool_compare_and_swap(
            &(list->end), last, node);
#endif
    }while( prev != last );

    last->next = node;
    last->data_ptr = data;
	// 表中节点数自增
    __asm__ __volatile__( "lock; incl %0" 
        : "+m" (list->size) :: "memory" );
    return 0;
}

// 取链表节点元素
static int list_next( listhead *list, void **pdata )
{
    listnode *node = 0; 
    listnode *tmp = 0;
    int ret = 0;

    do 
    {
        tmp = list->head;
        if ( tmp->next == NULL )
        {
            return -1;
        }

        *pdata = tmp->data_ptr;
        __asm__ __volatile__
        (
            "lock; cmpxchg %k1, %2; setz %0"
            : "=m" (ret) // result, %0
            : "r" (tmp->next), // new value
              "m" (list->head), // old value
              "a" (tmp) // %eax
            : "memory"
        );
    } while( !ret );

	// 表中节点数自减
    __asm__ __volatile__( "lock; decl %0" 
        : "+m" (list->size) :: "memory" );
    free( node );
    return 0;
}

// 统计链表中所有节点数据
static int list_count( listhead *list )
{
    int count = 0;
    listnode *node = list->head;

    FILE *fp = fopen( "list-nodes.txt", "w" );
    while( node != 0 )
    {
        ++count;
        fprintf( fp, "node=%p\n", node );
        node = node->next;
    }

    fprintf( fp, "list count is %d items, "
        "list size is %d items.\n", count, list->size );
    fprintf( stdout, "list count is %d items.\n", count );
    fclose( fp );
    return count;
}

// 对链表设置退出标志
static int list_exit( listhead *list )
{
    list->state = 1; // 退出
    return 0;
}

// 得到链表的退出状态
static int list_state( listhead *list )
{
    return list->state;
}

// 获取链表的节点个数
static int list_size( listhead *list )
{
    return list->size;
}

//
// 链表插入线程函数
static void *threadcb_add(void *arg)
{
    listhead *list = (listhead*)arg;
    int count = 100000;
    int loop = 0;

    for ( loop = 0; loop < count; loop++ )
    {
        list_add( list, &count );
    }

    printf( "%d插入了%d条数据\n", 
        (int)pthread_self(), count );
    return 0;
}

// 链表取节点线程函数
static void *threadcb_next(void *arg)
{
    listhead *list = (listhead*)arg;
    int count = 0;
    void *data = 0;

    while ( 1 )
    {
        if ( list_state(list) 
            && list_size(list) <= 0 )
        {
            break;
        }

        if ( list_next(list, &data) != 0 )
        {
            continue;
        }
        count++;
    }

    printf( "%d处理了%d条数据\n", 
        (int)pthread_self(), count );
    return 0;
}

//
int main()
{
    listhead list = {0};
    pthread_t thread[4] = {0};

    // 初始化
    listnode *first = (listhead*)malloc( sizeof(listnode) );
    memset( first, 0, sizeof(listnode) );
    list.head = first;//&list.first;
    list.end = first;//&list.first;

    pthread_create( &(thread[0]), 0, threadcb_add, &list );
    pthread_create( &(thread[1]), 0, threadcb_add, &list );
    pthread_create( &(thread[2]), 0, threadcb_next, &list );
    pthread_create( &(thread[3]), 0, threadcb_next, &list );
    
    pthread_join( thread[0], 0 );
    pthread_join( thread[1], 0 );
    list_count( &list );

    //pthread_create( &(thread[2]), 0, threadcb_next, &list );
    //pthread_create( &(thread[3]), 0, threadcb_next, &list );
    list_exit( &list );
    pthread_join( thread[2], 0 );
    pthread_join( thread[3], 0 );
    
    return 0;
}


makefile:

all:
	gcc -g -o list list.c -lpthread

.PHONY:run
run:
	./list

.PHONY:gdb
gdb:
	gdb ./list

.PHONY:clean
clean:
	rm ./list



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值