优化skynet_handle skynet_handle_grab (#2148)

Co-authored-by: lvzixun <lb151450@alibaba-inc.com>
This commit is contained in:
子熏
2026-03-31 22:43:38 +08:00
committed by GitHub
parent 6f84247f1f
commit 195a60d1f0
3 changed files with 91 additions and 15 deletions

View File

@@ -4,11 +4,21 @@
#include "skynet_imp.h" #include "skynet_imp.h"
#include "skynet_server.h" #include "skynet_server.h"
#include "rwlock.h" #include "rwlock.h"
#include "spinlock.h"
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#define HANDLE_CACHE_LINE 64
struct handle_reader_slot {
ATOM_INT active;
char _pad[HANDLE_CACHE_LINE - sizeof(ATOM_INT)];
};
static _Thread_local int TLS_SLOT_IDX = -1;
#define DEFAULT_SLOT_SIZE 4 #define DEFAULT_SLOT_SIZE 4
#define MAX_SLOT_SIZE 0x40000000 #define MAX_SLOT_SIZE 0x40000000
@@ -28,15 +38,60 @@ struct handle_storage {
int name_cap; int name_cap;
int name_count; int name_count;
struct handle_name *name; struct handle_name *name;
// distributed reader slots
ATOM_INT thread_idx;
int rslot_count;
struct handle_reader_slot *rslots;
}; };
static struct handle_storage *H = NULL; static struct handle_storage *H = NULL;
static inline void
handle_rlock(struct handle_storage *s) {
if (TLS_SLOT_IDX >= 0 && TLS_SLOT_IDX < s->rslot_count) {
for (;;) {
ATOM_STORE(&s->rslots[TLS_SLOT_IDX].active, 1);
if (!ATOM_LOAD(&s->lock.write)) {
break;
}
// Writer present — back off to avoid deadlock
ATOM_STORE(&s->rslots[TLS_SLOT_IDX].active, 0);
while (ATOM_LOAD(&s->lock.write)) { atomic_pause_(); }
}
} else {
rwlock_rlock(&s->lock);
}
}
static inline void
handle_runlock(struct handle_storage *s) {
if (TLS_SLOT_IDX >= 0 && TLS_SLOT_IDX < s->rslot_count) {
ATOM_STORE(&s->rslots[TLS_SLOT_IDX].active, 0);
} else {
rwlock_runlock(&s->lock);
}
}
static inline void
handle_wlock(struct handle_storage *s) {
rwlock_wlock(&s->lock);
// Additionally wait for all slot readers
for (int i = 0; i < s->rslot_count; i++) {
while (ATOM_LOAD(&s->rslots[i].active)) { atomic_pause_(); }
}
}
static inline void
handle_wunlock(struct handle_storage *s) {
rwlock_wunlock(&s->lock);
}
uint32_t uint32_t
skynet_handle_register(struct skynet_context *ctx) { skynet_handle_register(struct skynet_context *ctx) {
struct handle_storage *s = H; struct handle_storage *s = H;
rwlock_wlock(&s->lock); handle_wlock(s);
for (;;) { for (;;) {
int i; int i;
@@ -51,7 +106,7 @@ skynet_handle_register(struct skynet_context *ctx) {
s->slot[hash] = ctx; s->slot[hash] = ctx;
s->handle_index = handle + 1; s->handle_index = handle + 1;
rwlock_wunlock(&s->lock); handle_wunlock(s);
handle |= s->harbor; handle |= s->harbor;
return handle; return handle;
@@ -78,7 +133,7 @@ skynet_handle_retire(uint32_t handle) {
int ret = 0; int ret = 0;
struct handle_storage *s = H; struct handle_storage *s = H;
rwlock_wlock(&s->lock); handle_wlock(s);
uint32_t hash = handle & (s->slot_size-1); uint32_t hash = handle & (s->slot_size-1);
struct skynet_context * ctx = s->slot[hash]; struct skynet_context * ctx = s->slot[hash];
@@ -102,7 +157,7 @@ skynet_handle_retire(uint32_t handle) {
ctx = NULL; ctx = NULL;
} }
rwlock_wunlock(&s->lock); handle_wunlock(s);
if (ctx) { if (ctx) {
// release ctx may call skynet_handle_* , so wunlock first. // release ctx may call skynet_handle_* , so wunlock first.
@@ -119,14 +174,14 @@ skynet_handle_retireall() {
int n=0; int n=0;
int i; int i;
for (i=0;i<s->slot_size;i++) { for (i=0;i<s->slot_size;i++) {
rwlock_rlock(&s->lock); handle_rlock(s);
struct skynet_context * ctx = s->slot[i]; struct skynet_context * ctx = s->slot[i];
uint32_t handle = 0; uint32_t handle = 0;
if (ctx) { if (ctx) {
handle = skynet_context_handle(ctx); handle = skynet_context_handle(ctx);
++n; ++n;
} }
rwlock_runlock(&s->lock); handle_runlock(s);
if (handle != 0) { if (handle != 0) {
skynet_handle_retire(handle); skynet_handle_retire(handle);
} }
@@ -141,7 +196,7 @@ skynet_handle_grab(uint32_t handle) {
struct handle_storage *s = H; struct handle_storage *s = H;
struct skynet_context * result = NULL; struct skynet_context * result = NULL;
rwlock_rlock(&s->lock); handle_rlock(s);
uint32_t hash = handle & (s->slot_size-1); uint32_t hash = handle & (s->slot_size-1);
struct skynet_context * ctx = s->slot[hash]; struct skynet_context * ctx = s->slot[hash];
@@ -150,7 +205,7 @@ skynet_handle_grab(uint32_t handle) {
skynet_context_grab(result); skynet_context_grab(result);
} }
rwlock_runlock(&s->lock); handle_runlock(s);
return result; return result;
} }
@@ -159,7 +214,7 @@ uint32_t
skynet_handle_findname(const char * name) { skynet_handle_findname(const char * name) {
struct handle_storage *s = H; struct handle_storage *s = H;
rwlock_rlock(&s->lock); handle_rlock(s);
uint32_t handle = 0; uint32_t handle = 0;
@@ -180,7 +235,7 @@ skynet_handle_findname(const char * name) {
} }
} }
rwlock_runlock(&s->lock); handle_runlock(s);
return handle; return handle;
} }
@@ -237,17 +292,25 @@ _insert_name(struct handle_storage *s, const char * name, uint32_t handle) {
const char * const char *
skynet_handle_namehandle(uint32_t handle, const char *name) { skynet_handle_namehandle(uint32_t handle, const char *name) {
rwlock_wlock(&H->lock); handle_wlock(H);
const char * ret = _insert_name(H, name, handle); const char * ret = _insert_name(H, name, handle);
rwlock_wunlock(&H->lock); handle_wunlock(H);
return ret; return ret;
} }
void void
skynet_handle_init(int harbor) { skynet_handle_register_thread(void) {
int idx = ATOM_FINC(&H->thread_idx);
if (idx < H->rslot_count) {
TLS_SLOT_IDX = idx;
}
}
void
skynet_handle_init(int harbor, int thread) {
assert(H==NULL); assert(H==NULL);
struct handle_storage * s = skynet_malloc(sizeof(*H)); struct handle_storage * s = skynet_malloc(sizeof(*H));
s->slot_size = DEFAULT_SLOT_SIZE; s->slot_size = DEFAULT_SLOT_SIZE;
@@ -255,6 +318,14 @@ skynet_handle_init(int harbor) {
memset(s->slot, 0, s->slot_size * sizeof(struct skynet_context *)); memset(s->slot, 0, s->slot_size * sizeof(struct skynet_context *));
rwlock_init(&s->lock); rwlock_init(&s->lock);
// Distributed reader slots: workers + monitor + timer + socket
s->rslot_count = thread + 3;
size_t rslot_sz = (size_t)s->rslot_count * sizeof(struct handle_reader_slot);
s->rslots = (struct handle_reader_slot *)skynet_malloc(rslot_sz);
memset(s->rslots, 0, rslot_sz);
ATOM_INIT(&s->thread_idx, 0);
// reserve 0 for system // reserve 0 for system
s->harbor = (uint32_t) (harbor & 0xff) << HANDLE_REMOTE_SHIFT; s->harbor = (uint32_t) (harbor & 0xff) << HANDLE_REMOTE_SHIFT;
s->handle_index = 1; s->handle_index = 1;

View File

@@ -17,6 +17,7 @@ void skynet_handle_retireall();
uint32_t skynet_handle_findname(const char * name); uint32_t skynet_handle_findname(const char * name);
const char * skynet_handle_namehandle(uint32_t handle, const char *name); const char * skynet_handle_namehandle(uint32_t handle, const char *name);
void skynet_handle_init(int harbor); void skynet_handle_init(int harbor, int thread);
void skynet_handle_register_thread();
#endif #endif

View File

@@ -64,6 +64,7 @@ static void *
thread_socket(void *p) { thread_socket(void *p) {
struct monitor * m = p; struct monitor * m = p;
skynet_initthread(THREAD_SOCKET); skynet_initthread(THREAD_SOCKET);
skynet_handle_register_thread();
for (;;) { for (;;) {
int r = skynet_socket_poll(); int r = skynet_socket_poll();
if (r==0) if (r==0)
@@ -96,6 +97,7 @@ thread_monitor(void *p) {
int i; int i;
int n = m->count; int n = m->count;
skynet_initthread(THREAD_MONITOR); skynet_initthread(THREAD_MONITOR);
skynet_handle_register_thread();
for (;;) { for (;;) {
CHECK_ABORT CHECK_ABORT
for (i=0;i<n;i++) { for (i=0;i<n;i++) {
@@ -129,6 +131,7 @@ static void *
thread_timer(void *p) { thread_timer(void *p) {
struct monitor * m = p; struct monitor * m = p;
skynet_initthread(THREAD_TIMER); skynet_initthread(THREAD_TIMER);
skynet_handle_register_thread();
for (;;) { for (;;) {
skynet_updatetime(); skynet_updatetime();
skynet_socket_updatetime(); skynet_socket_updatetime();
@@ -158,6 +161,7 @@ thread_worker(void *p) {
struct monitor *m = wp->m; struct monitor *m = wp->m;
struct skynet_monitor *sm = m->m[id]; struct skynet_monitor *sm = m->m[id];
skynet_initthread(THREAD_WORKER); skynet_initthread(THREAD_WORKER);
skynet_handle_register_thread();
struct message_queue * q = NULL; struct message_queue * q = NULL;
while (!m->quit) { while (!m->quit) {
q = skynet_context_message_dispatch(sm, q, weight); q = skynet_context_message_dispatch(sm, q, weight);
@@ -273,7 +277,7 @@ skynet_start(struct skynet_config * config) {
} }
} }
skynet_harbor_init(config->harbor); skynet_harbor_init(config->harbor);
skynet_handle_init(config->harbor); skynet_handle_init(config->harbor, config->thread);
skynet_mq_init(); skynet_mq_init();
skynet_module_init(config->module_path); skynet_module_init(config->module_path);
skynet_timer_init(); skynet_timer_init();