mirror of
https://github.com/switchbrew/libnx.git
synced 2025-07-05 02:52:13 +02:00
added linked list and part of barrier
This commit is contained in:
parent
3513c91c3c
commit
a9d95be173
24
nx/include/switch/kernel/barrier.h
Normal file
24
nx/include/switch/kernel/barrier.h
Normal file
@ -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);
|
35
nx/include/switch/runtime/util/list.h
Normal file
35
nx/include/switch/runtime/util/list.h
Normal file
@ -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);
|
39
nx/source/kernel/barrier.c
Normal file
39
nx/source/kernel/barrier.c
Normal file
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
136
nx/source/runtime/util/list.c
Normal file
136
nx/source/runtime/util/list.c
Normal file
@ -0,0 +1,136 @@
|
||||
#include "runtime/util/list.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user