Add multithreaded BSD/socket support; revise BSD service type handling so that bsd:u is the default (since it has 22 worker threads as opposed to bsd:s's 11)

This commit is contained in:
fincs 2019-10-26 17:26:04 +02:00
parent bc13692938
commit 5340c7d7dc
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
4 changed files with 53 additions and 20 deletions

View File

@ -1,6 +1,13 @@
#pragma once #pragma once
#include "../../types.h" #include "../../types.h"
/// BSD service type used by the socket driver.
typedef enum {
BsdServiceType_User = BIT(0), ///< Uses bsd:u (default).
BsdServiceType_System = BIT(1), ///< Uses bsd:s.
BsdServiceType_Auto = BsdServiceType_User | BsdServiceType_System, ///< Tries to use bsd:s first, and if that fails uses bsd:u (official software behavior).
} BsdServiceType;
/// Configuration structure for socketInitalize /// Configuration structure for socketInitalize
typedef struct { typedef struct {
u32 bsdsockets_version; ///< Observed 1 on 2.0 LibAppletWeb, 2 on 3.0. u32 bsdsockets_version; ///< Observed 1 on 2.0 LibAppletWeb, 2 on 3.0.
@ -15,6 +22,9 @@ typedef struct {
u32 sb_efficiency; ///< Number of buffers for each socket (standard values range from 1 to 8). u32 sb_efficiency; ///< Number of buffers for each socket (standard values range from 1 to 8).
u32 num_bsd_sessions; ///< Number of BSD service sessions (typically 3).
BsdServiceType bsd_service_type; ///< BSD service type (typically \ref BsdServiceType_User).
size_t serialized_out_addrinfos_max_size; ///< For getaddrinfo. size_t serialized_out_addrinfos_max_size; ///< For getaddrinfo.
size_t serialized_out_hostent_max_size; ///< For gethostbyname/gethostbyaddr. size_t serialized_out_hostent_max_size; ///< For gethostbyname/gethostbyaddr.
bool bypass_nsd; ///< For name gethostbyname/getaddrinfo: bypass the Name Server Daemon. bool bypass_nsd; ///< For name gethostbyname/getaddrinfo: bypass the Name Server Daemon.
@ -33,7 +43,6 @@ Result socketGetLastSfdnsresResult(void);
void socketExit(void); void socketExit(void);
/// Initalize the socket driver using the default configuration. /// Initalize the socket driver using the default configuration.
static inline Result socketInitializeDefault(void) { NX_INLINE Result socketInitializeDefault(void) {
return socketInitialize(socketGetDefaultInitConfig()); return socketInitialize(NULL);
} }

View File

@ -35,7 +35,7 @@ extern __thread int g_bsdErrno; ///< Last errno, per-thread
/// Fetch the default configuration for bsdInitialize. /// Fetch the default configuration for bsdInitialize.
const BsdInitConfig *bsdGetDefaultInitConfig(void); const BsdInitConfig *bsdGetDefaultInitConfig(void);
/// Initialize the BSD service. /// Initialize the BSD service.
Result bsdInitialize(const BsdInitConfig *config); Result bsdInitialize(const BsdInitConfig *config, u32 num_sessions, u32 service_type);
/// Deinitialize the BSD service. /// Deinitialize the BSD service.
void bsdExit(void); void bsdExit(void);
Service* bsdGetServiceSession(void); Service* bsdGetServiceSession(void);
@ -73,8 +73,3 @@ int bsdClose(int fd);
int bsdDuplicateSocket(int sockfd); int bsdDuplicateSocket(int sockfd);
// TODO: Reverse-engineer GetResourceStatistics. Implement sendmmsg/recvmmsg (custom (un)serialization) // TODO: Reverse-engineer GetResourceStatistics. Implement sendmmsg/recvmmsg (custom (un)serialization)
/// Initialize the BSD service using the default configuration.
static inline Result bsdInitializeDefault(void) {
return bsdInitialize(bsdGetDefaultInitConfig());
}

View File

@ -84,6 +84,9 @@ static const SocketInitConfig g_defaultSocketInitConfig = {
.sb_efficiency = 4, .sb_efficiency = 4,
.num_bsd_sessions = 3,
.bsd_service_type = BsdServiceType_User,
.serialized_out_addrinfos_max_size = 0x1000, .serialized_out_addrinfos_max_size = 0x1000,
.serialized_out_hostent_max_size = 0x200, .serialized_out_hostent_max_size = 0x200,
.bypass_nsd = false, .bypass_nsd = false,
@ -96,6 +99,9 @@ const SocketInitConfig *socketGetDefaultInitConfig(void) {
Result socketInitialize(const SocketInitConfig *config) { Result socketInitialize(const SocketInitConfig *config) {
Result ret = 0; Result ret = 0;
if (!config)
config = &g_defaultSocketInitConfig;
BsdInitConfig bcfg = { BsdInitConfig bcfg = {
.version = config->bsdsockets_version, .version = config->bsdsockets_version,
@ -110,6 +116,14 @@ Result socketInitialize(const SocketInitConfig *config) {
.sb_efficiency = config->sb_efficiency, .sb_efficiency = config->sb_efficiency,
}; };
u32 num_bsd_sessions = config->num_bsd_sessions;
u32 bsd_service_type = config->bsd_service_type;
if (!num_bsd_sessions)
num_bsd_sessions = g_defaultSocketInitConfig.num_bsd_sessions;
if (!bsd_service_type)
bsd_service_type = g_defaultSocketInitConfig.bsd_service_type;
SfdnsresConfig sfdnsresConfig = { SfdnsresConfig sfdnsresConfig = {
.serialized_out_addrinfos_max_size = config->serialized_out_addrinfos_max_size, .serialized_out_addrinfos_max_size = config->serialized_out_addrinfos_max_size,
.serialized_out_hostent_max_size = config->serialized_out_hostent_max_size, .serialized_out_hostent_max_size = config->serialized_out_hostent_max_size,
@ -124,7 +138,7 @@ Result socketInitialize(const SocketInitConfig *config) {
ret = nifmInitialize(); ret = nifmInitialize();
if(R_FAILED(ret)) return ret; if(R_FAILED(ret)) return ret;
ret = bsdInitialize(&bcfg); ret = bsdInitialize(&bcfg, num_bsd_sessions, bsd_service_type);
if(R_SUCCEEDED(ret)) if(R_SUCCEEDED(ret))
dev = AddDevice(&g_socketDevoptab); dev = AddDevice(&g_socketDevoptab);
else { else {
@ -1614,7 +1628,7 @@ long gethostid(void) {
rc = nifmGetCurrentIpAddress(&id); rc = nifmGetCurrentIpAddress(&id);
if(R_SUCCEEDED(rc)) if(R_SUCCEEDED(rc))
return id; return id;
return INADDR_LOOPBACK; return INADDR_LOOPBACK;
} }
int gethostname(char *name, size_t namelen) { int gethostname(char *name, size_t namelen) {

View File

@ -15,6 +15,7 @@
#include "service_guard.h" #include "service_guard.h"
#include "kernel/shmem.h" #include "kernel/shmem.h"
#include "kernel/rwlock.h" #include "kernel/rwlock.h"
#include "sf/sessionmgr.h"
#include "services/bsd.h" #include "services/bsd.h"
typedef struct BsdSelectTimeval { typedef struct BsdSelectTimeval {
@ -27,6 +28,7 @@ __thread int g_bsdErrno;
static Service g_bsdSrv; static Service g_bsdSrv;
static Service g_bsdMonitor; static Service g_bsdMonitor;
static SessionMgr g_bsdSessionMgr;
static u64 g_bsdClientPid = -1; static u64 g_bsdClientPid = -1;
static TransferMemory g_bsdTmem; static TransferMemory g_bsdTmem;
@ -45,7 +47,7 @@ static const BsdInitConfig g_defaultBsdInitConfig = {
.sb_efficiency = 4, .sb_efficiency = 4,
}; };
NX_GENERATE_SERVICE_GUARD_PARAMS(bsd, (const BsdInitConfig *config), (config)); NX_GENERATE_SERVICE_GUARD_PARAMS(bsd, (const BsdInitConfig *config, u32 num_sessions, u32 service_type), (config, num_sessions, service_type));
// This function computes the minimal size of the transfer memory to be passed to @ref bsdInitalize. // This function computes the minimal size of the transfer memory to be passed to @ref bsdInitalize.
// Should the transfer memory be smaller than that, the BSD sockets service would only send // Should the transfer memory be smaller than that, the BSD sockets service would only send
@ -112,7 +114,10 @@ NX_INLINE int _bsdDispatchImpl(
if (in_data_size) if (in_data_size)
__builtin_memcpy(in, in_data, in_data_size); __builtin_memcpy(in, in_data, in_data_size);
Result rc = svcSendSyncRequest(srv.session); int slot = sessionmgrAttachClient(&g_bsdSessionMgr);
Result rc = svcSendSyncRequest(sessionmgrGetClientSession(&g_bsdSessionMgr, slot));
sessionmgrDetachClient(&g_bsdSessionMgr, slot);
int ret = -1; int ret = -1;
int errno_ = -1; int errno_ = -1;
void* out_ptr = NULL; void* out_ptr = NULL;
@ -187,19 +192,25 @@ const BsdInitConfig *bsdGetDefaultInitConfig(void) {
return &g_defaultBsdInitConfig; return &g_defaultBsdInitConfig;
} }
Result _bsdInitialize(const BsdInitConfig *config) { Result _bsdInitialize(const BsdInitConfig *config, u32 num_sessions, u32 service_type) {
if (!config) if (!config)
config = &g_defaultBsdInitConfig; config = &g_defaultBsdInitConfig;
const char* bsd_srv = "bsd:s"; SmServiceName bsd_srv = {0};
Result rc = smGetService(&g_bsdSrv, bsd_srv); Result rc = MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (R_FAILED(rc)) {
bsd_srv = "bsd:u"; if (service_type & BIT(1)) {
rc = smGetService(&g_bsdSrv, bsd_srv); bsd_srv = smEncodeName("bsd:s");
rc = smGetServiceWrapper(&g_bsdSrv, bsd_srv);
}
if (R_FAILED(rc) && (service_type & BIT(0))) {
bsd_srv = smEncodeName("bsd:u");
rc = smGetServiceWrapper(&g_bsdSrv, bsd_srv);
} }
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = smGetService(&g_bsdMonitor, bsd_srv); rc = smGetServiceWrapper(&g_bsdMonitor, bsd_srv);
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = tmemCreate(&g_bsdTmem, _bsdGetTransferMemSizeForConfig(config), 0); rc = tmemCreate(&g_bsdTmem, _bsdGetTransferMemSizeForConfig(config), 0);
@ -210,11 +221,15 @@ Result _bsdInitialize(const BsdInitConfig *config) {
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = _bsdStartMonitoring(g_bsdClientPid); rc = _bsdStartMonitoring(g_bsdClientPid);
if (R_SUCCEEDED(rc))
rc = sessionmgrCreate(&g_bsdSessionMgr, g_bsdSrv.session, num_sessions);
return rc; return rc;
} }
void _bsdCleanup(void) { void _bsdCleanup(void) {
g_bsdClientPid = 0; g_bsdClientPid = 0;
sessionmgrClose(&g_bsdSessionMgr);
serviceClose(&g_bsdMonitor); serviceClose(&g_bsdMonitor);
serviceClose(&g_bsdSrv); serviceClose(&g_bsdSrv);
tmemClose(&g_bsdTmem); tmemClose(&g_bsdTmem);