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

list.c:

///

#include

#include

#include

#include

#include

//

// 链表节点

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值