Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

for issue 45 CAS linked list #57

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions datastructs/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Mark some tasks phony to ensure proper building
.PHONY: all clean rebuild test linkedlist hashtable ringbuffer
.PHONY: all clean rebuild test linkedlist hashtable ringbuffer ll_atomic

#List of dependency files needed for compilation
all: linkedlist hashtable ringbuffer
all: linkedlist hashtable ringbuffer ll_atomic

rebuild: clean all

Expand All @@ -12,15 +12,20 @@ hashtable:
linkedlist:
cd linkedlist && make

ll_atomic:
cd ll_atomic && make

ringbuffer:
cd ringbuffer && make

test:
./linkedlist/test/test-list
./ll_atomic/test/test-list
./hashtable/test/test-hashtable
./ringbuffer/test/test-ringbuffer

clean:
cd linkedlist && make clean
cd ll_atomic && make clean
cd hashtable && make clean
cd ringbuffer && make clean
Binary file modified datastructs/linkedlist/test/test-linkedlist
Binary file not shown.
21 changes: 21 additions & 0 deletions datastructs/ll_atomic/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#Use the gcc compiler
CC = gcc
CFLAGS = -std=c99 -pedantic -Wall
#List of dependency files needed for compilation
DEPS = ll_atomic.c
LDFLAGS =
OBJS = ll_atomic.o tests

all: $(OBJS)

rebuild: clean all

linkedlist:
$(CC) $(CFLAGS) -c $(DEPS)

tests:
cd test && make

clean:
rm -f ll_atomic.o
cd test && make clean
96 changes: 96 additions & 0 deletions datastructs/ll_atomic/ll_atomic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "ll_atomic.h"

void
ll_init(struct list *ll)
{
ll->dummy.next = &ll->dummy;
ll->dummy.prev = &ll->dummy;
ll->size = 0;
}

void
ll_append(struct list *ll, struct ll_node *node)
{
atomic_fetch_add(&ll->size, 1);

struct ll_node *temp = &ll->dummy;
struct ll_node *ptr = (struct ll_node *)node;
struct ll_node *tail;

ptr->next = temp;

while (1){
tail = temp->prev;
ptr->prev = tail;
if (atomic_compare_exchange_strong(&temp->prev, &tail, ptr)) {
tail->next = ptr;
break;
}
}
}

void
ll_prepend(struct list *ll, struct ll_node *node)
{
atomic_fetch_add(&ll->size, 1);

struct ll_node *temp = &ll->dummy;
struct ll_node *ptr = (struct ll_node *)node;
struct ll_node *head;

ptr->next = temp;

while (1){
head = temp->next;
ptr->next = head;
if (atomic_compare_exchange_strong(&temp->next, &head, ptr)) {
head->prev = ptr;
break;
}
}
}

struct ll_node *
ll_first(struct list *ll)
{
struct ll_node *dummy = &ll->dummy;
struct ll_node *ptr, *next, *dummy_next;

ptr = dummy->next;
if (ptr == dummy) return NULL;

while (1) {
next = ptr->next;
if (atomic_compare_exchange_strong(&next->prev, &ptr, dummy)) {
dummy_next = dummy->next;
atomic_compare_exchange_strong(&dummy->next, &dummy_next, next);
break;
}
}

atomic_fetch_sub(&ll->size, 1);
return ptr;
}

struct ll_node *
ll_last(struct list *ll)
{
struct ll_node *dummy = &ll->dummy;
struct ll_node *ptr, *prev, *dummy_prev;

ptr = dummy->prev;

if(ptr == dummy) return NULL;

while (1) {
prev = ptr->prev;
if (atomic_compare_exchange_strong(&dummy->prev, &dummy_prev, prev)) {
dummy_prev = dummy->prev;
atomic_compare_exchange_strong(&dummy->prev, &dummy_prev, prev);
break;
}
}

atomic_fetch_sub(&ll->size, 1);
return ptr;
}
49 changes: 49 additions & 0 deletions datastructs/ll_atomic/ll_atomic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef LL_ATOMIC_
#define LL_ATMOIC_

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <stdatomic.h>

struct ll_node {
void *data;
struct ll_node * volatile next;
struct ll_node * volatile prev;

};

struct list {
struct ll_node dummy;
uint32_t size;
};

void
ll_init(struct list *ll);

struct ll_node *
ll_init_node(void *value);

static inline struct ll_node *
ll_head(struct list *ll) { return ll->dummy.next; }

static inline struct ll_node *
ll_tail(struct list *ll) { return ll->dummy.prev; }

int
ll_size(void);

void
ll_append(struct list *ll, struct ll_node *node);

void
ll_prepend(struct list *ll, struct ll_node *node);

struct ll_node *
ll_first(struct list *ll);

struct ll_node *
ll_last(struct list *ll);

#endif /*LL_ATOMIC*/
13 changes: 13 additions & 0 deletions datastructs/ll_atomic/test/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CC = gcc
CFLAGS = -std=c99 -Wall -pedantic
DEPS = ../ll_atomic.o
OBJ = test-linkedlist

all: linkedlist_test

rebuild: clean all

linkedlist_test:
$(CC) $(CFLAGS) test-ll.c -o $(OBJ) $(DEPS)
clean:
rm -f $(OBJ)
23 changes: 23 additions & 0 deletions datastructs/ll_atomic/test/test-ll.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "../ll_atomic.h"

int
main(void)
{
struct list ll;
struct ll_node node, *wat;
node.data = (void *) 99;
printf("%d\n", *((int*)&node.data));
ll_init(&ll);
ll_append(&ll, &node);
wat = ll_last(&ll);
printf("%d\n", *((int*)&wat->data));
node.data = (void *) 100;
ll_prepend(&ll, &node);
wat = ll_first(&ll);
printf("%d\n", *((int*)&wat->data));

return 0;
}