mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
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:
parent
bc13692938
commit
5340c7d7dc
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
|
||||||
}
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user