diff --git a/datastructs/Makefile b/datastructs/Makefile index 62e54d6..a557168 100644 --- a/datastructs/Makefile +++ b/datastructs/Makefile @@ -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 @@ -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 diff --git a/datastructs/linkedlist/test/test-linkedlist b/datastructs/linkedlist/test/test-linkedlist index e93f5e3..d3b9728 100755 Binary files a/datastructs/linkedlist/test/test-linkedlist and b/datastructs/linkedlist/test/test-linkedlist differ diff --git a/datastructs/ll_atomic/Makefile b/datastructs/ll_atomic/Makefile new file mode 100644 index 0000000..a6694d5 --- /dev/null +++ b/datastructs/ll_atomic/Makefile @@ -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 diff --git a/datastructs/ll_atomic/ll_atomic.c b/datastructs/ll_atomic/ll_atomic.c new file mode 100644 index 0000000..1521442 --- /dev/null +++ b/datastructs/ll_atomic/ll_atomic.c @@ -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; +} diff --git a/datastructs/ll_atomic/ll_atomic.h b/datastructs/ll_atomic/ll_atomic.h new file mode 100644 index 0000000..cacfc42 --- /dev/null +++ b/datastructs/ll_atomic/ll_atomic.h @@ -0,0 +1,49 @@ +#ifndef LL_ATOMIC_ +#define LL_ATMOIC_ + +#include +#include +#include +#include +#include + +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*/ diff --git a/datastructs/ll_atomic/test/Makefile b/datastructs/ll_atomic/test/Makefile new file mode 100644 index 0000000..892852e --- /dev/null +++ b/datastructs/ll_atomic/test/Makefile @@ -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) diff --git a/datastructs/ll_atomic/test/test-ll.c b/datastructs/ll_atomic/test/test-ll.c new file mode 100644 index 0000000..f0375d9 --- /dev/null +++ b/datastructs/ll_atomic/test/test-ll.c @@ -0,0 +1,23 @@ +#include +#include +#include +#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; +}