Skip to content
This repository has been archived by the owner on Sep 21, 2021. It is now read-only.

Commit

Permalink
add condvar
Browse files Browse the repository at this point in the history
  • Loading branch information
misson20000 committed Sep 13, 2018
1 parent d80eb0b commit 10ac72b
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 1 deletion.
48 changes: 48 additions & 0 deletions include/libtransistor/condvar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* @file libtransistor/condvar.h
* @brief Condition variables
*/

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include<libtransistor/types.h>
#include<libtransistor/mutex.h>

typedef struct {
uint32_t key;
} trn_condvar_t;

#define TRN_CONDVAR_STATIC_INITIALIZER {.key = 0}

/**
* @brief Creates a condition variable
*
* Alternatively, a statically allocated condition variable
* may be initialized with /ref TRN_CONDVAR_STATIC_INITIALIZER
*/
void trn_condvar_create(trn_condvar_t *condvar);

/**
* @brief Signals n threads waiting on the condition variable, or -1 for all of them
*/
result_t trn_condvar_signal(trn_condvar_t *condvar, int n);

/**
* @brief Waits for the condition variable to be signalled
*
* @param timeout How long (in nanoseconds) to wait, or -1 for no timeout
*/
result_t trn_condvar_wait(trn_condvar_t *condvar, trn_mutex_t *mutex, uint64_t timeout) REQUIRES(mutex);

/**
* @brief Destroys a condition variable
*/
void trn_condvar_destroy(trn_condvar_t *condvar);

#ifdef __cplusplus
}
#endif
1 change: 1 addition & 0 deletions include/libtransistor/nx.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ extern "C" {
#include<libtransistor/tls.h>
#include<libtransistor/util.h>
#include<libtransistor/mutex.h>
#include<libtransistor/condvar.h>
#include<libtransistor/thread.h>

// filesystem
Expand Down
28 changes: 28 additions & 0 deletions lib/condvar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include<libtransistor/condvar.h>

#include<libtransistor/svc.h>
#include<libtransistor/tls.h>

void trn_condvar_create(trn_condvar_t *condvar) {
condvar->key = 0;
}

result_t trn_condvar_signal(trn_condvar_t *condvar, int n) {
return svcSignalProcessWideKey(&condvar->key, n);
}

result_t trn_condvar_wait(trn_condvar_t *condvar, trn_mutex_t *mutex, uint64_t timeout) NO_THREAD_SAFETY_ANALYSIS {
result_t r;

r = svcWaitProcessWideKeyAtomic((void*) &mutex->lock, &condvar->key, get_thread_handle(), timeout);

if(r == 0xea01) {
trn_mutex_lock(mutex);
}

return r;
}

void trn_condvar_destroy(trn_condvar_t *condvar) {
condvar->key = -1;
}
2 changes: 1 addition & 1 deletion mk/tests.mk
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# LIBTRANSISTOR TESTS

libtransistor_TESTS := malloc bsd_ai_packing bsd sfdnsres nv helloworld hid hexdump args ssp stdin vi gpu display am sqfs_img audio_output init_fini_arrays ipc_server pthread ipc_fs fs_stress cpp unwind cpp_exceptions cpp_dynamic_memory hid_init_stress usb usb_serial thread mutex override_heap # fs_release_inodes
libtransistor_TESTS := malloc bsd_ai_packing bsd sfdnsres nv helloworld hid hexdump args ssp stdin vi gpu display am sqfs_img audio_output init_fini_arrays ipc_server pthread ipc_fs fs_stress cpp unwind cpp_exceptions cpp_dynamic_memory hid_init_stress usb usb_serial thread mutex override_heap condvar # fs_release_inodes
libtransistor_DYNAMIC_TESTS := simple dlfcn bad_resolution preemption elf

# RUN RULES
Expand Down
1 change: 1 addition & 0 deletions mk/transistor_headers.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ libtransistor_HEADER_NAMES := \
alloc_pages.h \
audio.h \
collections/list.h \
condvar.h \
display/binder.h \
display/display.h \
display/fence.h \
Expand Down
1 change: 1 addition & 0 deletions mk/transistor_objects.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
libtransistor_OBJECT_NAMES := \
address_space.o \
alloc_pages.o \
condvar.o \
crt0_common.o \
display/binder.o \
display/display.o \
Expand Down
51 changes: 51 additions & 0 deletions test/test_condvar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include<libtransistor/util.h>
#include<libtransistor/mutex.h>
#include<libtransistor/condvar.h>
#include<libtransistor/thread.h>
#include<libtransistor/svc.h>

#include<stdio.h>

static trn_mutex_t mutex;
static trn_condvar_t condvar;
static volatile bool pred = 0;

void other_thread(void *arg) {
printf("O: other thread started\n");

printf("O: trying to lock mutex\n");
trn_mutex_lock(&mutex);
printf("O: acquired mutex\n");
while(!pred) {
printf("O: waiting on condvar...\n");
trn_condvar_wait(&condvar, &mutex, -1);
printf("O: woke up\n");
}
trn_mutex_unlock(&mutex);
}

int main(int argc, char *argv[]) {
result_t r;
trn_mutex_create(&mutex);
trn_condvar_create(&condvar);

trn_thread_t thread;
ASSERT_OK(fail, trn_thread_create(&thread, other_thread, NULL, -1, -2, 1024 * 64, NULL));
ASSERT_OK(fail_thread, trn_thread_start(&thread));

printf("M: started other thread\n");
svcSleepThread(5000000000);
printf("M: signalling spuriously\n");
trn_condvar_signal(&condvar, 1);
svcSleepThread(5000000000);
printf("M: signalling\n");
pred = 1;
trn_condvar_signal(&condvar, 1);

trn_thread_join(&thread, -1);

fail_thread:
trn_thread_destroy(&thread);
fail:
return r;
}

0 comments on commit 10ac72b

Please sign in to comment.