From 200f22578700b82c5a2d2052c9fda0d9e431d25f Mon Sep 17 00:00:00 2001 From: Stefan Zabka Date: Fri, 12 Jun 2020 00:05:28 +0200 Subject: THIS SHIT WORKS --- 04_exercise/CMakeLists.txt | 2 +- 04_exercise/arena/arena_list.c | 67 ++++++++++++++++++++++++++---------------- 04_exercise/main.c | 2 +- 04_exercise/rwlock/rwlock.c | 67 ++++++++++++++++++++++++++++++++++++++++++ 04_exercise/rwlock/rwlock.h | 16 ++++++++++ 04_exercise/threadpool.c | 4 --- 6 files changed, 126 insertions(+), 32 deletions(-) create mode 100644 04_exercise/rwlock/rwlock.c create mode 100644 04_exercise/rwlock/rwlock.h diff --git a/04_exercise/CMakeLists.txt b/04_exercise/CMakeLists.txt index 8cea647..18f3fb7 100644 --- a/04_exercise/CMakeLists.txt +++ b/04_exercise/CMakeLists.txt @@ -23,4 +23,4 @@ target_link_libraries(arena_test PRIVATE arena_list) add_library(rwlock rwlock/rwlock.c) target_include_directories(rwlock PUBLIC rwlock) -target_link_libraries(rwlock INTERFACE warnings) +target_link_libraries(rwlock INTERFACE warnings) \ No newline at end of file diff --git a/04_exercise/arena/arena_list.c b/04_exercise/arena/arena_list.c index 4becef6..73b126c 100644 --- a/04_exercise/arena/arena_list.c +++ b/04_exercise/arena/arena_list.c @@ -3,12 +3,20 @@ // #include "arena_list.h" #include -#include #include #include #include +static const bool DEBUG = false; +bool listContains(List const * const list ,Node const * const needle) { + for(Node * current = list ->first; current != NULL; current = current->next) { + if(current == needle) { + return true; + } + } + return false; +} Node *listPopFront(List *list) { Node *front = list->first; if (front == NULL) { @@ -77,7 +85,8 @@ AtomicArenaList alInit(Node *arena, size_t size) { } int alPush(AtomicArenaList *al, void *value) { - fprintf(stderr, "Thread %lu: Pushing \n", pthread_self() % 1000); + if(DEBUG) + fprintf(stderr, "Thread %lu: Pushing \n", pthread_self() % 1000); rwLockWrite(&al->lock); Node *current = listPopFront(&al->freeList); // List is empty @@ -92,43 +101,49 @@ int alPush(AtomicArenaList *al, void *value) { } int alRemoveElem(AtomicArenaList *al, void *value) { - fprintf(stderr, "Thread %lu: Removing element \n", pthread_self() % 1000); + if(DEBUG) + fprintf(stderr, "Thread %lu: Removing element \n", pthread_self() % 1000); rwLockWrite(&al->lock); - for (size_t i = 0; i < al->size; ++i) { + size_t i = 0; + for (; i < al->size; ++i) { if (al->arena[i].value != value) { continue; } - Node *node = &al->arena[i]; - if (node == al->activeList.first) { - listPopFront(&al->activeList); - listPushFront(&al->freeList, node); - atomic_char *a = &al->lock; - rwUnlockWrite(a); - return 0; - } - if (node == al->activeList.last) { - listPopBack(&al->activeList); - listPushFront(&al->freeList, node); - rwUnlockWrite(&al->lock); - return 0; - } - // The node is somewhere in the middle - Node *prev = node->prev; - Node *next = node->next; - - next->prev = prev; - prev->next = next; + } + Node *node = &al->arena[i]; + if(listContains(&al->activeList,node) || i == al->size) { + rwUnlockWrite(&al->lock); + return -1; + } + if (node == al->activeList.first) { + listPopFront(&al->activeList); + listPushFront(&al->freeList, node); + atomic_char *a = &al->lock; + rwUnlockWrite(a); + return 0; + } + if (node == al->activeList.last) { + listPopBack(&al->activeList); listPushFront(&al->freeList, node); rwUnlockWrite(&al->lock); return 0; } + // The node is somewhere in the middle + Node *prev = node->prev; + Node *next = node->next; + + next->prev = prev; + prev->next = next; + + listPushFront(&al->freeList, node); rwUnlockWrite(&al->lock); - return -1; + return 0; } void *alFindLastElem(AtomicArenaList *al, SearchFunction f) { - fprintf(stderr, "Thread %lu: Finding last element \n", pthread_self() % 1000); + if(DEBUG) + fprintf(stderr, "Thread %lu: Finding last element \n", pthread_self() % 1000); rwLockRead(&al->lock); diff --git a/04_exercise/main.c b/04_exercise/main.c index e73dd98..69be10b 100644 --- a/04_exercise/main.c +++ b/04_exercise/main.c @@ -17,7 +17,7 @@ static TASK(long, fib, long) int main() { setvbuf(stdout, NULL, _IONBF, 0); - if (tpInit(1) != 0) + if (tpInit(4) != 0) perror("Thread Pool initialization failed"), exit(-1); atexit(&tpRelease); for (long i = 0; i <= 20; ++i) diff --git a/04_exercise/rwlock/rwlock.c b/04_exercise/rwlock/rwlock.c new file mode 100644 index 0000000..3de5083 --- /dev/null +++ b/04_exercise/rwlock/rwlock.c @@ -0,0 +1,67 @@ +// +// Created by stefan on 11.06.20. +// + +#include "rwlock.h" +#include +#include +#include +#include + +static const bool DEBUG = false; + + +void rwLockWrite(atomic_char *lock) { + char status; + bool succeeded; + do { + status = RW_UNLOCKED; + succeeded = atomic_compare_exchange_weak(lock, &status, RW_WRITE_LOCKED); + } while (!succeeded); + if(DEBUG) { + fprintf(stderr, "Thread %lu: Aquired Write Lock \n", pthread_self() % 1000); + } + +} + +void rwUnlockWrite(atomic_char *lock) { + char expected = RW_WRITE_LOCKED; + if (!atomic_compare_exchange_strong(lock, &expected, RW_UNLOCKED)) { + fprintf(stderr, "Couldn't unlock from writelock. Lock was at %d", expected); + perror("Lock got into undefined state"); + exit(-1); + } + if(DEBUG) { + fprintf(stderr, "Thread %lu: Released Write Lock \n", pthread_self() % 1000); + } + if (sched_yield() < 0) { + perror("Couldn't sleep. This shouldn't happen."); + exit(-1); + } + +} +void rwLockRead(atomic_char *lock) { + while (atomic_load(lock) == RW_WRITE_LOCKED) { + + } + atomic_fetch_add(lock, 1); + if(DEBUG) { + fprintf(stderr, "Thread %lu: Aquired Read Lock \n", pthread_self() % 1000); + } +} +void rwUnlockRead(atomic_char *lock) { + char value = atomic_load(lock); + if (value < 1) { + fprintf(stderr, "Couldn't unlock from readlock. Lock was at %d", value); + perror("Lock got into undefined state"); + exit(-1); + } + atomic_fetch_sub(lock, 1); + if(DEBUG) { + fprintf(stderr, "Thread %lu: Released Read Lock \n", pthread_self() % 1000); + } + if (sched_yield() < 0) { + perror("Couldn't sleep. This shouldn't happen."); + exit(-1); + } +} \ No newline at end of file diff --git a/04_exercise/rwlock/rwlock.h b/04_exercise/rwlock/rwlock.h new file mode 100644 index 0000000..aa27f09 --- /dev/null +++ b/04_exercise/rwlock/rwlock.h @@ -0,0 +1,16 @@ +// +// Created by stefan on 11.06.20. +// + +#ifndef BETRIEBSYSTEME_RWLOCK_H +#define BETRIEBSYSTEME_RWLOCK_H +#include + +static const char RW_WRITE_LOCKED = -1; +static const char RW_UNLOCKED = 0; +void rwLockWrite(atomic_char *lock); +void rwUnlockWrite(atomic_char *lock); +void rwLockRead(atomic_char *lock); +void rwUnlockRead(atomic_char *lock); + +#endif // BETRIEBSYSTEME_RWLOCK_H diff --git a/04_exercise/threadpool.c b/04_exercise/threadpool.c index 54d4448..f644412 100644 --- a/04_exercise/threadpool.c +++ b/04_exercise/threadpool.c @@ -116,10 +116,6 @@ void tpAsync(Future *future) { } void tpAwait(Future *future) { - if (atomic_load(&future->status) == FUT_DONE) { - alRemoveElem(&threadPool.al, (void *)future); - return; - } if (atomic_load(&future->status) == FUT_WAITING) { tryRunningFuture(future); } -- cgit v1.2.3-54-g00ecf