This commit is contained in:
Juan Antonio Hernández Cánovas 2018-08-31 19:22:51 +00:00 committed by GitHub
commit 1fa1819489
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 408 additions and 0 deletions

View File

@ -28,6 +28,7 @@ extern "C" {
#include "switch/kernel/condvar.h"
#include "switch/kernel/thread.h"
#include "switch/kernel/semaphore.h"
#include "switch/kernel/barrier.h"
#include "switch/kernel/virtmem.h"
#include "switch/kernel/detect.h"
#include "switch/kernel/random.h"
@ -76,6 +77,7 @@ extern "C" {
#include "switch/runtime/nxlink.h"
#include "switch/runtime/util/utf.h"
#include "switch/runtime/util/list.h"
#include "switch/runtime/devices/console.h"
#include "switch/runtime/devices/usb_comms.h"

View File

@ -0,0 +1,49 @@
/**
* @file barrier.h
* @brief Barrier synchronization primitive.
* @author Yordrar
* @copyright libnx Authors
*/
#pragma once
#include "condvar.h"
#include "mutex.h"
#include "thread.h"
#include "../runtime/util/list.h"
typedef struct barrier {
List threads_registered;
List threads_waiting;
Mutex mutex;
} Barrier;
/**
* @brief Allocates memory for a barrier
* @param b Barrier object
*/
void barrierInit(Barrier* b);
/**
* @brief Frees the memory allocated for a barrier
* @param b Barrier object
*/
void barrierFree(Barrier* b);
/**
* @brief Registers a thread that is going to use the specified barrier
* @param b Barrier object
* @param thread The thread to register
*/
void barrierRegister(Barrier* b, Thread* thread);
/**
* @brief Unegisters a thread that is not going to use anymore the specified barrier
* @param b Barrier object
* @param thread The thread to unregister
*/
void barrierUnregister(Barrier* b, Thread* thread);
/**
* @brief Waits until all processes registered in the barrier call this function, if a not registered thread calls this function, it returns without waiting
* @param b Barrier object
*/
void barrierWait(Barrier* b);

View File

@ -0,0 +1,135 @@
/**
* @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/rwlock.h"
#include "../../kernel/thread.h"
typedef struct node {
void* item;
struct node* next;
} Node;
typedef struct list {
Node* header;
Node* last;
u32 num_nodes;
RwLock mutex;
} List;
/**
* @brief Allocates memory for a list
* @param l List object
*/
void listInit(List* l);
/**
* @brief Frees memory allocated for a list
* @param l List object
*/
void listFree(List* l);
/**
* @brief Inserts something in a position
* @param l List object
* @param item A pointer to the thing you want to insert
* @param pos The position to insert (0 is the first position)
*/
void listInsert(List* l, void* item, u32 pos);
/**
* @brief Inserts something in the first position
* @param l List object
* @param item A pointer to the thing you want to insert
*/
static inline void listInsertFirst(List* l, void* item) {
listInsert(l, item, 0);
}
/**
* @brief Inserts something at the end of the list
* @param l List object
* @param item A pointer to the thing you want to insert
*/
void listInsertLast(List* l, void* item);
/**
* @brief Deletes the node of the list which has the item specified (makes a pointer comparison to ckeck that)
* @param l List object
* @param item A pointer to the thing you want to delete
*/
void listDelete(List* l, void* item);
/**
* @brief Checks if the item is inserted in the list (makes a pointer comparison to ckeck that)
* @param l List object
* @param item A pointer to the thing you want to check
* @return true if the item is in the list, false otherwise
*/
bool listIsInserted(List* l, void* item);
/**
* @brief Returns the number of items inserted in the list
* @param l List object
* @return The number of nodes (the number of inserted things) in the list
*/
u32 listGetNumNodes(List* l);
/**
* @brief Returns the item inserted in an specified position
* @param l List object
* @param pos The position of the item
* @return A pointer to that item, NULL if it isn't found
*/
void* listGetItem(List* l, u32 pos);
/**
* @brief Inserts the item in the first position
* @param l List object
* @param item A pointer to something to store
*/
static inline void listPushFront(List* l, void* item) {
listInsert(l, item, 0);
}
/**
* @brief Returns the item inserted in the first position and deletes it
* @param l List object
* @return A pointer to that item, NULL if the list is empty
*/
void* listPopFront(List* l);
/**
* @brief Returns the item inserted in the first position
* @param l List object.
* @return A pointer to that item, NULL if the list is empty
*/
void* listPeekFront(List* l);
/**
* @brief Inserts the item in the last position
* @param l List object.
* @param item A pointer to something you want to insert
*/
static inline void listPushBack(List* l, void* item) {
listInsertLast(l, item);
}
/**
* @brief Returns the item inserted in the last position and deletes it
* @param l List object.
* @return A pointer to that item, NULL if the list is empty
*/
void* listPopBack(List* l);
/**
* @brief Returns the item inserted in the last position
* @param l List object.
* @return A pointer to that item, NULL if the list is empty
*/
void* listPeekBack(List* l);

View File

@ -0,0 +1,50 @@
#include "kernel/barrier.h"
#include "../internal.h"
void barrierInit(Barrier* b) {
mutexInit(&b->mutex);
mutexLock(&b->mutex);
listInit(&b->threads_registered);
listInit(&b->threads_waiting);
mutexUnlock(&b->mutex);
}
void barrierFree(Barrier* b) {
mutexLock(&b->mutex);
listFree(&b->threads_registered);
listFree(&b->threads_waiting);
mutexUnlock(&b->mutex);
}
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 = getThreadVars()->thread_ptr;
if(!listIsInserted(&b->threads_registered, (void*)thread)) {
return;
}
mutexLock(&b->mutex);
if(listGetNumNodes(&b->threads_registered) == listGetNumNodes(&b->threads_waiting)+1) {
while(listGetNumNodes(&b->threads_waiting) > 0) {
Thread* current_thread = listGetItem(&b->threads_waiting, 0);
svcSetThreadActivity(current_thread->handle, 0);
listDelete(&b->threads_waiting, (void*)current_thread);
}
mutexUnlock(&b->mutex);
}
else {
listInsertLast(&b->threads_waiting, (void*)thread);
mutexUnlock(&b->mutex);
svcSleepThread(0);
}
}

View File

@ -0,0 +1,172 @@
#include "runtime/util/list.h"
#include <stdlib.h>
void listInit(List* l) {
rwlockInit(&l->mutex);
rwlockWriteLock(&l->mutex);
Node* header = (Node*)malloc(sizeof(Node));
header->item = NULL;
header->next = NULL;
l->header = header;
l->last = header;
l->num_nodes = 0;
rwlockWriteUnlock(&l->mutex);
}
void listFree(List* l) {
rwlockWriteLock(&l->mutex);
Node* aux = l->header;
while(aux != NULL) {
Node* erase = aux;
aux = aux->next;
free(erase);
}
l->header = NULL;
l->last = NULL;
l->num_nodes = 0;
rwlockWriteUnlock(&l->mutex);
}
void listInsert(List* l, void* item, u32 pos) {
rwlockReadLock(&l->mutex);
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;
if(pos == l->num_nodes) {
l->last = new;
}
l->num_nodes++;
rwlockWriteUnlock(&l->mutex);
}
void listInsertLast(List* l, void* item) {
rwlockWriteLock(&l->mutex);
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);
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);
}
void listDeleteAtPos(List* l, u32 pos) {
rwlockReadLock(&l->mutex);
if(pos >= l->num_nodes || pos < 0) {
return;
}
Node* aux = l->header;
for(int i = pos; i > 0; i++) {
aux = aux->next;
}
Node* delete = aux->next;
aux->next = delete->next;
free(delete);
l->num_nodes--;
rwlockReadUnlock(&l->mutex);
}
bool listIsInserted(List* l, void* item) {
rwlockReadLock(&l->mutex);
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);
u32 result = l->num_nodes;
rwlockReadUnlock(&l->mutex);
return result;
}
void* listGetItem(List* l, u32 pos) {
rwlockReadLock(&l->mutex);
if(pos >= l->num_nodes || pos < 0) {
return NULL;
}
Node* aux = l->header->next;
for(u32 i = pos; i > 0; i--) {
aux = aux->next;
}
void* result = aux->item;
rwlockReadUnlock(&l->mutex);
return result;
}
void* listPopFront(List* l) {
rwlockReadLock(&l->mutex);
if(l->num_nodes == 0) {
return NULL;
}
void* result = listGetItem(l, 0);
listDeleteAtPos(l, 0);
rwlockReadUnlock(&l->mutex);
return result;
}
void* listPeekFront(List* l) {
rwlockReadLock(&l->mutex);
if(l->num_nodes == 0) {
return NULL;
}
void* result = listGetItem(l, 0);
rwlockReadUnlock(&l->mutex);
return result;
}
void* listPopBack(List* l) {
rwlockReadLock(&l->mutex);
if(l->num_nodes == 0) {
return NULL;
}
void* result = listGetItem(l, l->num_nodes-1);
listDeleteAtPos(l, l->num_nodes-1);
rwlockReadUnlock(&l->mutex);
return result;
}
void* listPeekBack(List* l) {
rwlockReadLock(&l->mutex);
if(l->num_nodes == 0) {
return NULL;
}
void* result = listGetItem(l, l->num_nodes-1);
rwlockReadUnlock(&l->mutex);
return result;
}