高级操作系统之同步锁代码
高级操作系统之同步锁代码
读优先
#define N 10
#define M 10
#define READTIMES 100000
#define WRITETIMES 100000
#include "csapp.h"
int readcnt; /* Initially 0 */
sem_t mutex, w; /* Both initially 1 */
void *read_thread(void *vargp);
void *write_thread(void *vargp);
int main() {
readcnt = 0;
pthread_t readers[N];
pthread_t writers[M];
sem_init(&mutex, 0, N);
sem_init(&w, 0, 1);
int i;
for (i=0;i<N;i++)
Pthread_create(&readers[i], NULL, read_thread, (void *)i);
for (i=0;i<M;i++)
Pthread_create(&writers[i], NULL, write_thread, (void *)i);
for (i=0;i<N;i++)
Pthread_join(readers[i], NULL);
for (i=0;i<M;i++)
Pthread_join(writers[i], NULL);
}
void *read_thread(void *vargp)
{
for (int i=0;i<READTIMES;i++) {
P(&mutex);
readcnt++;
if (readcnt == 1) /* First in */
P(&w);
V(&mutex);
/* Reading happens here */
printf("Reader (%d) is reading, readcnt = %d, i=%d\n", (int)vargp, readcnt, i);
if (i==READTIMES-1)
printf("Reader (%d) finished!\n", (int)vargp);
P(&mutex);
readcnt--;
if (readcnt == 0) /* Last out */
V(&w);
V(&mutex);
}
}
void *write_thread(void *vargp)
{
for (int i=0;i<WRITETIMES;i++) {
P(&w);
/* Writing here */
printf("writing...i=%d\n", i);
if(i==WRITETIMES-1)
printf("Writer (%d) finished!\n", (int)vargp);
V(&w);
}
}
读写公平
#define N 10
#define READTIMES 100000
#define WRITETIMES 10000
#include "csapp.h"
sem_t common_sem, w; /* Both initially 1 */
void *read_thread(void *vargp);
void *write_thread(void *vargp);
int main() {
pthread_t readers[N];
pthread_t writers[N];
sem_init(&common_sem, 0, N);
sem_init(&w, 0, 1);
int i;
for (i=0;i<N;i++) {
Pthread_create(&readers[i], NULL, read_thread, (void *)i);
Pthread_create(&writers[i], NULL, write_thread, (void *)i);
}
for (i=0;i<N;i++) {
Pthread_join(readers[i], NULL);
Pthread_join(writers[i], NULL);
}
}
void *read_thread(void *vargp)
{
for (int i=0;i<READTIMES;i++) {
P(&common_sem);
/* Reading happens here */
printf("Reader (%d) is reading, i=%d\n", (int)vargp, i);
if (i==READTIMES-1)
printf("Reader (%d) finished!\n", (int)vargp);
V(&common_sem);
}
}
void *write_thread(void *vargp)
{
int j;
for (int i=0;i<WRITETIMES;i++) {
P(&w);
for (j=0;j<N;j++)
P(&common_sem);
V(&w);
/* Writing here */
printf("writing...i=%d\n", i);
if(i==WRITETIMES-1)
printf("Writer (%d) finished!\n", (int)vargp);
for (j=0;j<N;j++)
V(&common_sem);
}
}
写优先
#define N 10
#define M 10
#define READTIMES 100000
#define WRITETIMES 100000
#include "csapp.h"
int readcnt, writecnt; /* Initially 0 */
sem_t r, w, rcnt, wcnt; /* Both initially 1 */
void *read_thread(void *vargp);
void *write_thread(void *vargp);
int main() {
readcnt = 0;
writecnt = 0;
pthread_t readers[N];
pthread_t writers[M];
sem_init(&r, 0, 1);
sem_init(&w, 0, 1);
sem_init(&rcnt, 0, 1);
sem_init(&wcnt, 0, 1);
int i;
for (i=0;i<N;i++)
Pthread_create(&readers[i], NULL, read_thread, (void *)i);
for (i=0;i<M;i++)
Pthread_create(&writers[i], NULL, write_thread, (void *)i);
for (i=0;i<N;i++)
Pthread_join(readers[i], NULL);
for (i=0;i<M;i++)
Pthread_join(writers[i], NULL);
}
void *read_thread(void *vargp)
{
for (int i=0;i<READTIMES;i++) {
P(&r);
P(&rcnt);
readcnt++;
if (readcnt == 1) /* First in */
P(&w);
V(&rcnt);
V(&r);
/* Reading happens here */
printf("Reader (%d) is reading, readcnt = %d, i=%d\n", (int)vargp, readcnt, i);
if (i==READTIMES-1)
printf("Reader (%d) finished!\n", (int)vargp);
P(&rcnt);
readcnt--;
if (readcnt == 0) /* Last out */
V(&w);
V(&rcnt);
}
}
void *write_thread(void *vargp)
{
for (int i=0;i<WRITETIMES;i++) {
P(&wcnt);
writecnt++;
if (writecnt == 1)
P(&r);
V(&wcnt);
P(&w);
/* Writing here */
printf("writing...i=%d\n", i);
if(i==WRITETIMES-1)
printf("Writer (%d) finished!\n", (int)vargp);
V(&w);
P(&wcnt);
writecnt--;
if (writecnt == 0)
V(&r);
V(&wcnt);
}
}
有锁链表
#define N 100
#define Total 100000000
#include "csapp.h"
typedef struct __node_t { // basic node structure
int key;
struct __node_t *next;
} node_t;
typedef struct __list_t { // basic list structure
node_t *head;
pthread_mutex_t lock;
} list_t;
list_t mylist;
void List_Init(list_t *L) {
L->head = NULL;
pthread_mutex_init(&L->lock, NULL);
}
void *worker(void *argp) {
for (int i=0;i<Total/N;i++)
List_Insert(&mylist, (int)((int)argp<<16+i));
}
void main() {
List_Init(&mylist);
pthread_t workers[N];
int i;
for (i=0;i<N;i++) {
Pthread_create(&workers[i], NULL, worker, (void *)i);
}
for (i=0;i<N;i++) {
Pthread_join(workers[i], NULL);
}
}
void List_Insert(list_t *L, int key) {
// synchronization not needed
node_t *new = malloc(sizeof(node_t));
if (new == NULL) {
perror("malloc");
return;
}
new->key = key;
// just lock critical section
pthread_mutex_lock(&L->lock);
new->next = L->head;
L->head = new;
pthread_mutex_unlock(&L->lock);
}
int List_Lookup(list_t *L, int key) {
int rv = -1;
pthread_mutex_lock(&L->lock);
node_t *curr = L->head;
while (curr) {
if (curr->key == key) {
rv = 0;
break;
}
curr = curr->next;
}
pthread_mutex_unlock(&L->lock);
return rv;
}
无锁链表
#define N 100
#define Total 100000000
#include "csapp.h"
typedef struct __node_t { // basic node structure
int key;
struct __node_t *next;
} node_t;
typedef struct __list_t { // basic list structure
node_t *head;
// pthread_mutex_t lock;
} list_t;
list_t mylist;
/* return 1 when swapping happens;
retnrun 0 when not*/
int CAS(unsigned long *dst, unsigned long oldVal, unsigned long newVal)
{
unsigned char ret;
//printf("(%lu,%lu,%lu)", *dst, oldVal, newVal);
__asm__ __volatile__ (
" lock cmpxchgq %2,%1\n"
" sete %0\n" // ret=zf (0:oldVal!=*dst ; 1:oldVal==*dst)
: "=q" (ret), "=m" (*dst)
: "r" (newVal), "m" (*dst), "a" (oldVal)
: "memory");
//printf("->(%lu,%lu,%lu):%d\r\n", *dst, oldVal, newVal, ret);
//above assembly returns 0 in case of failure
if (ret)
return 1;
return 0;
}
void List_Init(list_t *L) {
L->head = NULL;
// pthread_mutex_init(&L->lock, NULL);
}
void printList(list_t *L) {
node_t* p = L->head;
printf("!! p init = %d\r\n", (int)p);
while(p!=NULL) {
printf("p->key = %d\n", p->key);
p = p->next;
}
}
int getListLen(list_t *L) {
int len = 0;
node_t* p = L->head;
while(p != NULL) {
p = p->next;
len++;
}
return len;
}
void *worker(void *argp) {
for (int i=0;i<Total/N;i++)
List_Insert(&mylist, i);
//printList(&mylist);
}
void main() {
List_Init(&mylist);
pthread_t workers[N];
int i;
for (i=0;i<N;i++) {
Pthread_create(&workers[i], NULL, worker, (void *)i);
}
for (i=0;i<N;i++) {
Pthread_join(workers[i], NULL);
}
int len = getListLen(&mylist);
printf("list len = %d\n", len);
}
void List_Insert(list_t *L, int key) {
// synchronization not needed
node_t *new = malloc(sizeof(node_t));
if (new == NULL) {
perror("malloc");
return;
}
new->key = key;
// just lock critical section
//pthread_mutex_lock(&L->lock);
int tmp;
do {
new->next = L->head;
tmp = CAS(&(L->head), new->next, new);
}while(tmp == 0);
//printf("CurNode(%lu, %d, %lu)\r\n", new, new->key, new->next);
//printList(L);
//L->head = new;
//pthread_mutex_unlock(&L->lock);
}
int List_Lookup(list_t *L, int key) {
int rv = -1;
//pthread_mutex_lock(&L->lock);
node_t *curr = L->head;
while (curr) {
if (curr->key == key) {
rv = 0;
break;
}
curr = curr->next;
}
//pthread_mutex_unlock(&L->lock);
return rv;
}