seqlock算法的变体

时间:2013-12-01 10:46:17

标签: c linux multithreading algorithm

有人可以提供一些有关如何解决以下任务的示例/提示/指示:资源可能由两种类型的进程使用:黑色和白色。当白色进程使用资源时,黑色进程不能使用它,反之亦然。实现对资源的访问,避免饥饿。在较旧的帖子中,我被建议使用seqlock算法的变体,但我无法想出如何为此分配调整该算法。

编辑:这是我到目前为止编写的代码

#include <stdio.h>
#include <pthread.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

struct RW;
struct RW
{
    volatile int num_reads_in_progress;
    volatile int num_writes;
    pthread_cond_t reader_cv;
    pthread_cond_t writer_cv;
    pthread_mutex_t lock;
};
char *buf;
void signal_next(struct RW *b);
extern char *xx_read(struct RW *); 
extern void xx_write(struct RW *, char *); 

// Precondition: b->lock must be locked before this function is called
void signal_next(struct RW *b)
{
    if (b->num_writes > 0)
    {
        // if any writes are waiting wake one up
        pthread_cond_signal(&b->writer_cv);
    }
    else
    {
        // if are no writes pending, wake up all the readers
        pthread_cond_broadcast(&b->reader_cv);
    }
}



void *ts_read(void *vb);
void *ts_read(void *vb) 
{
    struct RW *b = vb; 
    pthread_mutex_lock(&b->lock);
    while (b->num_writes > 0)
    {
        // cond_wait unlocks the mutex, waits to be signaled, then re-acquires the mutex
        pthread_cond_wait(&b->reader_cv, &b->lock);
    }
    // By there b->num_writes must be 0
    b->num_reads_in_progress++;
    pthread_mutex_unlock(&b->lock);

    buf = xx_read(b); 

    pthread_mutex_lock(&b->lock);
    b->num_reads_in_progress--;
    signal_next(b);
    pthread_mutex_unlock(&b->lock);
    return 0; 
}


void *ts_write(void *vb);
void *ts_write(void *vb) 
{
    struct RW *b = vb; 
    pthread_mutex_lock(&b->lock);
    b->num_writes++;

    if (b->num_writes > 1 || b->num_reads_in_progress > 0)
    {
        // cond_wait unlocks the mutex, waits to be signaled,
        // then re-acquires the mutex
        pthread_cond_wait(&b->writer_cv, &b->lock);
    }
    pthread_mutex_unlock(&b->lock);

    xx_write(b, buf); 
    pthread_mutex_lock(&b->lock);
    b->num_writes--;
    signal_next(b);
    pthread_mutex_unlock(&b->lock);
    return 0; 
}

int main(void)
{
    pthread_t white[3];
    pthread_t black[3];
    struct RW *rw;
    rw = malloc(sizeof(struct RW));
    int i;
    for (i = 0; i < 3; i++)
    {
        pthread_create(&white[i], NULL, &ts_read, &rw);
    }

    for (i = 0; i < 3; i++)
    {
        pthread_create(&black[i], NULL, ts_write, &rw);
    }
    for (i = 0; i < 3; i++)
    {
        pthread_join(white[i], NULL);
    }
    for (i = 0; i < 3; i++)
    {
        pthread_join(black[i], NULL);
    }
    return 0;
}

2 个答案:

答案 0 :(得分:0)

您需要锁定和解锁的互斥锁。基本上,您可以将互斥锁视为布尔值,该值为true或false(如果您愿意,可以锁定或解锁)。

当黑色进程访问资源时,应锁定互斥锁。而且,另一方面,当白色试图访问它时,它应首先检查互斥锁的状态。如果互斥锁的状态被锁定,则必须等到互斥锁被解锁。

伪代码:

unsigned char mutex = 0;

//processBlack tries to access resource
  if(mutex == 1)
      while(mutex != 0);
  mutex = 1;
  //now the mutex is unlocked, do whatever you want
  mutex = 0; //do not forget to unlock it.


//processWhite tries to access resource
  if(mutex == 1)
      while(mutex != 0);
  mutex = 1;
  //now the mutex is unlocked, do whatever you want
  mutex = 0; //do not forget to unlock it.

答案 1 :(得分:0)

如果你想使用seqlock机制,请参阅第5.7.4节:

http://www.makelinux.net/ldd3/chp-5-sect-7

这里是作家的例子:

http://www.sao.ru/hq/sts/linux/doc/porting_to_26/22818.html