Linux futex

下面的代码是我学习Linux futex时写的实验代码,存在大量谬误和不规范的地方,有许多认识上的错误。
这只是实验代码,实际工作中不会如此编程。

futex_t::wake 实际是一个计数器,防止在调用futex_wait函数前调用futex_wake而出现的死等现象,
函数futex只在满足(*addr1 == val)时等待。

futex_wait函数与futex_wake函数配合使用,前者等待后者唤醒。
futex_lock函数与futex_unlock函数配合使用,前者加锁后者解锁。

应该是对数据加锁,而不应该对代码加锁。但这只是测试, 实际编程中不应如此使用。

编译使用如下命令:
g++ -g -W -Wall -Wextra -o mytest main.cpp -lpthread
执行:
./mytest
停止:
Ctrl-C

参考文献:
futex(2),futex(7),Linux内核文档,Linux内核源代码futex.c。



main.cpp:


// 2010年 07月 28日 星期三 13:01:43 CST
// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng)
// K.I.S.S
// S.P.O.T
// linux-2.6.XX/Document/
// linux-2.6.xx/kernel/futex.c

#include
#include

#include
#include
#include
#include
#include

using namespace std;


#define futex(addr1, op, val, rel, addr2, val3)    /
    syscall(SYS_futex, addr1, op, val, rel, addr2, val3)

struct futex_t {
    int wake;
    int lock;
    int wlock;
};

inline static void futex_init(futex_t *);
inline static int futex_wake(futex_t *);
inline static int futex_wait(futex_t *);
inline static int futex_lock(futex_t *);
inline static int futex_unlock(futex_t *);


static void *work_thread(void *);
static void *work_send(void *);

static int count = 0;

int main()
{
    struct futex_t ftx;
    pthread_t tid[6];

    futex_init(&ftx);

    pthread_create(&tid[3], 0, work_send, (void *)&ftx);
    pthread_create(&tid[1], 0, work_thread, (void *)&ftx);
    pthread_create(&tid[2], 0, work_thread, (void *)&ftx);
    pthread_create(&tid[5], 0, work_send, (void *)&ftx);
    pthread_create(&tid[0], 0, work_thread, (void *)&ftx);
    pthread_create(&tid[4], 0, work_send, (void *)&ftx);

    for(int i = 0; i < 6; ++i)
        pthread_join(tid[i], 0);

    return 0;
}

void *work_thread(void *p)
{
    struct futex_t *ftx = (struct futex_t *)p;
    //sleep(2);

    for(;;) {
        futex_wait(ftx);

        futex_lock(ftx);
        cout << pthread_self() << endl;
        cout << "Hello,world!/n";
        cout << count++ << endl;
        cout << "******************************/n";
        futex_unlock(ftx);
    }
    return (void *)0;
}

void *work_send(void *p)
{
    futex_t *ftx = (struct futex_t *)p;
    for(int i = 0; i < 3000; ++i)
        futex_wake(ftx);
    return (void *)0;
}

inline static void futex_init(futex_t *ftx)
{
    ftx->lock = 0;
    ftx->wake = 0;
    ftx->wlock = 0;
}

inline static int futex_wake(futex_t *ftx)
{
    __sync_fetch_and_add(&ftx->wake, 1);
    //__sync_lock_test_and_set(&ftx->wake, 1);
    return futex(&ftx->wake, FUTEX_WAKE, 1, 0, 0, 0);
}

inline static int futex_wait(futex_t *ftx)
{
    futex(&ftx->wlock, FUTEX_LOCK_PI, 0, 0, 0, 0);
    int ret = futex(&ftx->wake, FUTEX_WAIT, 0, 0, 0, 0);
    __sync_fetch_and_sub(&ftx->wake, 1);
    futex(&ftx->wlock, FUTEX_UNLOCK_PI, 0, 0, 0, 0);
    return (ret && errno == EWOULDBLOCK ? 1 : ret);
}

inline static int futex_lock(futex_t *ftx)
{
    return futex(&ftx->lock, FUTEX_LOCK_PI, 0, 0, 0, 0);
}

inline static int futex_unlock(futex_t *ftx)
{
    return futex(&ftx->lock, FUTEX_UNLOCK_PI, 0, 0, 0, 0);
}

你可能感兴趣的:(GNU/Linix,C/C++)