Implement per-thread non-blocking behavior for srvGetServiceHandle...
implement srvWaitForPortRegistered and srvIsPortRegistered as well.
This commit is contained in:
parent
abf8064771
commit
c598c445cd
@ -10,6 +10,14 @@ Result srvInit(void);
|
||||
/// Exits the service API.
|
||||
void srvExit(void);
|
||||
|
||||
/**
|
||||
* @brief Makes srvGetServiceHandle non-blocking for the current thread (or blocking, the default), in case of unavailable (full) requested services.
|
||||
* @param blocking Whether srvGetServiceHandle should be non-blocking.
|
||||
* srvGetServiceHandle will always block if the service hasn't been registered yet,
|
||||
* use srvIsServiceRegistered to check whether that is the case or not.
|
||||
*/
|
||||
void srvSetBlockingPolicy(bool nonBlocking);
|
||||
|
||||
/**
|
||||
* @brief Gets the current service API session handle.
|
||||
* @return The current service API session handle.
|
||||
@ -20,6 +28,9 @@ Handle *srvGetSessionHandle(void);
|
||||
* @brief Retrieves a service handle, retrieving from the environment handle list if possible.
|
||||
* @param out Pointer to write the handle to.
|
||||
* @param name Name of the service.
|
||||
* @return 0 if no error occured,
|
||||
* 0xD8E06406 if the caller has no right to access the service,
|
||||
* 0xD0401834 if the requested service port is full and srvGetServiceHandle is non-blocking (see @ref srvSetBlockingPolicy).
|
||||
*/
|
||||
Result srvGetServiceHandle(Handle* out, const char* name);
|
||||
|
||||
@ -50,6 +61,9 @@ Result srvUnregisterService(const char* name);
|
||||
* @brief Retrieves a service handle.
|
||||
* @param out Pointer to output the handle to.
|
||||
* @param name Name of the service.
|
||||
* * @return 0 if no error occured,
|
||||
* 0xD8E06406 if the caller has no right to access the service,
|
||||
* 0xD0401834 if the requested service port is full and srvGetServiceHandle is non-blocking (see @ref srvSetBlockingPolicy).
|
||||
*/
|
||||
Result srvGetServiceHandleDirect(Handle* out, const char* name);
|
||||
|
||||
@ -73,6 +87,12 @@ Result srvUnregisterPort(const char* name);
|
||||
*/
|
||||
Result srvGetPort(Handle* out, const char* name);
|
||||
|
||||
/**
|
||||
* @brief Waits for a port to be registered.
|
||||
* @param name Name of the port to wait for registration.
|
||||
*/
|
||||
Result srvWaitForPortRegistered(const char* name);
|
||||
|
||||
/**
|
||||
* @brief Subscribes to a notification.
|
||||
* @param notificationId ID of the notification.
|
||||
@ -112,3 +132,10 @@ Result srvPublishAndGetSubscriber(u32* processIdCountOut, u32* processIdsOut, u3
|
||||
* @param name Name of the service to check.
|
||||
*/
|
||||
Result srvIsServiceRegistered(bool* registeredOut, const char* name);
|
||||
|
||||
/**
|
||||
* @brief Checks whether a port is registered.
|
||||
* @param registeredOut Pointer to output the registration status to.
|
||||
* @param name Name of the port to check.
|
||||
*/
|
||||
Result srvIsPortRegistered(bool* registeredOut, const char* name);
|
||||
|
@ -26,6 +26,9 @@ typedef struct
|
||||
// FS session override
|
||||
u32 fs_magic;
|
||||
Handle fs_session;
|
||||
|
||||
// Whether srvGetServiceHandle is non-blocking in case of full service ports.
|
||||
bool srv_blocking_policy;
|
||||
} ThreadVars;
|
||||
|
||||
static inline ThreadVars* getThreadVars(void)
|
||||
|
@ -14,9 +14,17 @@
|
||||
#include <3ds/os.h>
|
||||
#include <3ds/services/srvpm.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
static Handle srvHandle;
|
||||
static int srvRefCount;
|
||||
|
||||
static bool srvGetBlockingPolicy(void)
|
||||
{
|
||||
ThreadVars *tv = getThreadVars();
|
||||
return tv->magic == THREADVARS_MAGIC && tv->srv_blocking_policy;
|
||||
}
|
||||
|
||||
Result srvInit(void)
|
||||
{
|
||||
Result rc = 0;
|
||||
@ -43,6 +51,12 @@ void srvExit(void)
|
||||
srvHandle = 0;
|
||||
}
|
||||
|
||||
void srvSetBlockingPolicy(bool nonBlocking)
|
||||
{
|
||||
ThreadVars *tv = getThreadVars();
|
||||
tv->srv_blocking_policy = nonBlocking;
|
||||
}
|
||||
|
||||
Handle *srvGetSessionHandle(void)
|
||||
{
|
||||
return &srvHandle;
|
||||
@ -128,7 +142,7 @@ Result srvGetServiceHandleDirect(Handle* out, const char* name)
|
||||
cmdbuf[0] = IPC_MakeHeader(0x5,4,0); // 0x50100
|
||||
strncpy((char*) &cmdbuf[1], name,8);
|
||||
cmdbuf[3] = strnlen(name, 8);
|
||||
cmdbuf[4] = 0x0;
|
||||
cmdbuf[4] = (u32)srvGetBlockingPolicy(); // per-thread setting, default is blocking
|
||||
|
||||
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
|
||||
|
||||
@ -184,6 +198,20 @@ Result srvGetPort(Handle* out, const char* name)
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result srvWaitForPortRegistered(const char* name)
|
||||
{
|
||||
Result rc = 0;
|
||||
u32* cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x8,4,0); // 0x80100
|
||||
strncpy((char*) &cmdbuf[1], name,8);
|
||||
cmdbuf[3] = strnlen(name, 8);
|
||||
cmdbuf[4] = 0x1;
|
||||
|
||||
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result srvSubscribe(u32 notificationId)
|
||||
{
|
||||
Result rc = 0;
|
||||
@ -269,3 +297,21 @@ Result srvIsServiceRegistered(bool* registeredOut, const char* name)
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result srvIsPortRegistered(bool* registeredOut, const char* name)
|
||||
{
|
||||
Handle port;
|
||||
Result rc = srvGetPort(&port, name);
|
||||
|
||||
if(rc == 0xD8801BFA)
|
||||
{
|
||||
if(registeredOut) *registeredOut = false;
|
||||
return 0;
|
||||
}
|
||||
else if(R_SUCCEEDED(rc))
|
||||
{
|
||||
if(registeredOut) *registeredOut = true;
|
||||
svcCloseHandle(port);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ void __system_initSyscalls(void)
|
||||
tv->reent = _impure_ptr;
|
||||
tv->thread_ptr = NULL;
|
||||
tv->tls_tp = __tls_start-8; // ARM ELF TLS ABI mandates an 8-byte header
|
||||
tv->srv_blocking_policy = false;
|
||||
|
||||
u32 tls_size = __tdata_lma_end - __tdata_lma;
|
||||
if (tls_size)
|
||||
|
@ -33,6 +33,7 @@ static void _thread_begin(void* arg)
|
||||
tv->reent = &t->reent;
|
||||
tv->thread_ptr = t;
|
||||
tv->tls_tp = (u8*)t->stacktop-8; // ARM ELF TLS ABI mandates an 8-byte header
|
||||
tv->srv_blocking_policy = false;
|
||||
t->ep(t->arg);
|
||||
threadExit(0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user