From a9d95be173e631835e90fda13c59c184c2b10099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Antonio=20Hern=C3=A1ndez=20C=C3=A1novas?= Date: Fri, 24 Aug 2018 00:36:49 +0200 Subject: [PATCH] added linked list and part of barrier --- nx/include/switch/kernel/barrier.h | 24 +++++ nx/include/switch/runtime/util/list.h | 35 +++++++ nx/source/kernel/barrier.c | 39 ++++++++ nx/source/runtime/util/list.c | 136 ++++++++++++++++++++++++++ 4 files changed, 234 insertions(+) create mode 100644 nx/include/switch/kernel/barrier.h create mode 100644 nx/include/switch/runtime/util/list.h create mode 100644 nx/source/kernel/barrier.c create mode 100644 nx/source/runtime/util/list.c diff --git a/nx/include/switch/kernel/barrier.h b/nx/include/switch/kernel/barrier.h new file mode 100644 index 00000000..acd23b9c --- /dev/null +++ b/nx/include/switch/kernel/barrier.h @@ -0,0 +1,24 @@ +/** + * @file barrier.h + * @brief Barrier synchronization primitive. + * @author Yordrar + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "condvar.h" +#include "mutex.h" +#include "../runtime/util/list.h" + +typedef struct barrier { + List threads_registered; + List threads_waiting; + RwLock mutex; + bool isInited; +} Barrier; + +void barrierInit(Barrier* b); +void barrierFree(Barrier* b); +void barrierRegister(Barrier* b, Thread* thread); +void barrierUnregister(Barrier* b, Thread* thread); +void barrierWait(Barrier* b, Thread* thread); diff --git a/nx/include/switch/runtime/util/list.h b/nx/include/switch/runtime/util/list.h new file mode 100644 index 00000000..7faa4a73 --- /dev/null +++ b/nx/include/switch/runtime/util/list.h @@ -0,0 +1,35 @@ +/** + * @file list.h + * @brief Singly Linked List data structure. + * @author Yordrar + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../kernel/condvar.h" +#include "../kernel/mutex.h" + +typedef struct node { + void* item; + Node* next; +} Node; + +typedef struct list { + Node* header; + Node* last; + u32 num_nodes; + RwLock mutex; + bool isInited; +} List; + +void listInit(List* l); +void listFree(List* l); +void listInsert(List* l, void* item, u32 pos); +static inline void listInsertFirst(List* l, void* item) { + listInsert(l, item, 0); +} +void listInsertLast(List* l, void* item); +void listDelete(List* l, void* item); +bool listIsInserted(List* l, void* item); +u32 listGetNumNodes(List* l); +void* listGetItem(List* l, u32 pos); \ No newline at end of file diff --git a/nx/source/kernel/barrier.c b/nx/source/kernel/barrier.c new file mode 100644 index 00000000..88603abe --- /dev/null +++ b/nx/source/kernel/barrier.c @@ -0,0 +1,39 @@ +#include "kernel/barrier.h" + +void barrierInit(Barrier* b) { + rwlockWriteLock(b->mutex); + if(b->isInited) { + return; + } + listInit(b->threads_registered); + listInit(b->threads_waiting); + b->isInited = true; + rwlockWriteUnlock(b->mutex); +} + +void barrierFree(Barrier* b); + +void barrierRegister(Barrier* b, Thread* thread) { + if(listIsInserted(b->threads_registered, (void*)thread)) { + return; + } + listInsertLast(b->threads_registered, (void*)thread); +} + +void barrierUnregister(Barrier* b, Thread* thread) { + listDelete(b->threads_registered, (void*)thread); +} + +void barrierWait(Barrier* b, Thread* thread) { + if(!listIsInserted(b->threads_registered)) { + return; + } + threadPause((void*)thread); + listInsertLast(b->threads_waiting, thread); + + if(listGetNumNodes(b->threads_registered) == listGetNumNodes(b->threads_waiting)) { + while(listGetNumNodes(b->threads_waiting) > 0) { + threadResume(listGetItem(b->threads_waiting, 0)); + } + } +} \ No newline at end of file diff --git a/nx/source/runtime/util/list.c b/nx/source/runtime/util/list.c new file mode 100644 index 00000000..e634f841 --- /dev/null +++ b/nx/source/runtime/util/list.c @@ -0,0 +1,136 @@ +#include "runtime/util/list.h" +#include + +void listInit(List* l) { + rwlockWriteLock(l->mutex); + if(l->isInited) { + return; + } + Node* header = (Node*)malloc(sizeof(Node)); + header->item = NULL; + header->next = NULL; + + l->header = header; + l->last = header; + l->num_nodes = 0; + l->isInited = true; + rwlockWriteUnlock(l->mutex); +} + +void listFree(List* l) { + rwlockWriteLock(l->mutex); + if(!l->isInited) { + return; + } + Node* aux = l->header; + while(aux != NULL) { + free(aux); + aux = aux->next; + } + l->header = NULL; + l->last = NULL; + l->num_nodes = 0; + l->isInited = false; + rwlockWriteUnlock(l->mutex); +} + +void listInsert(List* l, void* item, u32 pos) { + rwlockReadLock(l->mutex); + if(!l->isInited) { + return; + } + if(pos > l->num_nodes || pos < 0) { + return; + } + rwlockReadUnlock(l->mutex); + + rwlockWriteLock(l->mutex); + Node* aux = l->header; + for(u32 i = pos; i > 0; i--) { + aux = aux->next; + } + + Node* new = (Node*)malloc(sizeof(Node)); + new->item = item; + new->next = aux->next; + aux->next = new; + + l->num_nodes++; + rwlockWriteUnlock(l->mutex); +} + +void listInsertLast(List* l, void* item) { + rwlockWriteLock(l->mutex); + if(!l->isInited) { + return; + } + Node* new = (Node*)malloc(sizeof(Node)); + new->item = item; + new->next = NULL; + + l->last->next = new; + l->last = new; + rwlockWriteUnlock(l->mutex); +} + +void listDelete(List* l, void* item) { + rwlockWriteLock(l->mutex); + if(!l->isInited) { + return; + } + + Node* aux = l->header; + while(aux->next != NULL && aux->next->item != item) { + aux = aux->next; + } + + if(aux->next != NULL && aux->next->item == item) { + Node* delete = aux->next; + aux->next = delete->next; + free(delete); + l->num_nodes--; + } + + rwlockWriteUnlock(l->mutex); +} + +bool listIsInserted(List* l, void* item) { + rwlockReadLock(l->mutex); + if(!l->isInited) { + return; + } + Node* aux = l->header; + while(aux != NULL && aux->item != item) { + aux = aux->next; + } + bool result = aux == NULL ? false : true; + rwlockReadUnlock(l->mutex); + return result; +} + +u32 listGetNumNodes(List* l) { + rwlockReadLock(l->mutex); + if(!l->isInited) { + return; + } + u32 result = l->num_nodes; + rwlockReadUnlock(l->mutex); + return result; +} + +void* listGetItem(List* l, u32 pos) { + rwlockReadLock(l->mutex); + if(!l->isInited) { + return; + } + if(pos >= l->num_nodes || pos < 0) { + return; + } + Node* aux = l->header->next; + for(u32 i = pos; i > 0; i--) { + aux = aux->next; + } + void* result = aux->item; + rwlockReadUnlock(l->mutex); + return result; +} \ No newline at end of file