summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Zabka <zabkaste@hu-berlin.de>2020-06-12 00:05:28 +0200
committerStefan Zabka <zabkaste@hu-berlin.de>2020-06-12 00:05:28 +0200
commit200f22578700b82c5a2d2052c9fda0d9e431d25f (patch)
tree49ff00735c15d7bd5cfb23089159440b788ff193
parentb9771b85d4f543af78465985e6350c0ca57f4c70 (diff)
downloadbetriebssysteme-200f22578700b82c5a2d2052c9fda0d9e431d25f.tar.gz
betriebssysteme-200f22578700b82c5a2d2052c9fda0d9e431d25f.zip
THIS SHIT WORKS
-rw-r--r--04_exercise/CMakeLists.txt2
-rw-r--r--04_exercise/arena/arena_list.c67
-rw-r--r--04_exercise/main.c2
-rw-r--r--04_exercise/rwlock/rwlock.c67
-rw-r--r--04_exercise/rwlock/rwlock.h16
-rw-r--r--04_exercise/threadpool.c4
6 files changed, 126 insertions, 32 deletions
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 <pthread.h>
-#include <sched.h>
#include <stdio.h>
#include <unistd.h>
#include <rwlock.h>
+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 <stdbool.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+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 <stdatomic.h>
+
+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);
}