optimize fiber_mutex by using context switch when the owner and waiter are in the same thread

This commit is contained in:
zhengshuxin 2022-11-18 16:47:10 +08:00
parent f5d6b15f33
commit 1f2f79c192
6 changed files with 85 additions and 14 deletions

View File

@ -9,7 +9,8 @@ extern "C" {
typedef struct ACL_FIBER_MUTEX ACL_FIBER_MUTEX;
#define FIBER_MUTEX_F_LOCK_TRY (1 << 0)
#define FIBER_MUTEX_F_LOCK_TRY (1 << 0)
#define FIBER_MUTEX_F_SWITCH_FIRST (1 << 1)
FIBER_API ACL_FIBER_MUTEX *acl_fiber_mutex_create(unsigned flag);
FIBER_API void acl_fiber_mutex_free(ACL_FIBER_MUTEX *mutex);

View File

@ -488,6 +488,15 @@ static int peek_more(EVENT_URING *ep)
return -1;
}
if (ret == -ETIME) {
printf("%s(%d): ETIME\n", __FUNCTION__, __LINE__);
}
if (ret == -ECANCELED) {
printf("%s(%d): ECANCELED\n", __FUNCTION__, __LINE__);
}
if (ctx == NULL) {
printf("%s(%d): ctx NULL\n", __FUNCTION__, __LINE__);
}
if (ret == -ETIME || ret == -ECANCELED || ctx == NULL) {
continue;
}
@ -555,6 +564,15 @@ AGAIN:
return -1;
}
if (ret == -ETIME) {
printf("%s(%d): ETIME\n", __FUNCTION__, __LINE__);
}
if (ret == -ECANCELED) {
printf("%s(%d): ECANCELED\n", __FUNCTION__, __LINE__);
}
if (ctx == NULL) {
printf("%s(%d): ctx NULL\n", __FUNCTION__, __LINE__);
}
if (ret == -ETIME || ret == -ECANCELED || ctx == NULL) {
return 1;
}
@ -631,8 +649,8 @@ EVENT *event_io_uring_create(int size)
__FUNCTION__, __LINE__, strerror(-ret), eu->sqe_size);
abort();
} else {
printf("%s(%d): init io_uring ok, size=%zd\r\n",
__FUNCTION__, __LINE__, eu->sqe_size);
printf("%s(%d): thread-%lu init io_uring ok, size=%zd\r\n",
__FUNCTION__, __LINE__, pthread_self(), eu->sqe_size);
}
if (!(params.features & IORING_FEAT_FAST_POLL)) {

View File

@ -713,6 +713,7 @@ static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *),
head = ring_pop_head(&__thread_fiber->dead);
if (head == NULL) {
fiber = __fiber_alloc_fn(fiber_start, attr);
fiber->tid = pthread_self();
} else {
fiber = APPL(head, ACL_FIBER, me);
}

View File

@ -44,6 +44,7 @@ struct SYNC_WAITER;
struct ACL_FIBER {
FIBER_BASE *base;
pthread_t tid;
fiber_status_t status;
RING me;
unsigned id;

View File

@ -57,7 +57,6 @@ static int fiber_mutex_lock_once(ACL_FIBER_MUTEX *mutex)
if (pthread_mutex_trylock(&mutex->thread_lock) == 0) {
array_delete(mutex->waiters, pos, NULL);
pthread_mutex_unlock(&mutex->lock);
return 0;
}
@ -147,7 +146,13 @@ int acl_fiber_mutex_unlock(ACL_FIBER_MUTEX *mutex)
}
if (fiber) {
sync_waiter_wakeup(fiber->sync, fiber);
if (!(mutex->flags & FIBER_MUTEX_F_SWITCH_FIRST)) {
sync_waiter_wakeup(fiber->sync, fiber);
} else if (pthread_self() == fiber->tid) {
acl_fiber_ready(fiber);
} else {
sync_waiter_wakeup(fiber->sync, fiber);
}
}
return 0;

View File

@ -5,6 +5,7 @@
#include "../stamp.h"
static int __fibers_count = 10;
static int __event_type = FIBER_EVENT_KERNEL;
static void fiber_main(ACL_FIBER *fiber, void *ctx)
{
@ -36,13 +37,12 @@ static void test1(void)
acl_fiber_create(fiber_main, l, 320000);
}
acl_fiber_schedule();
acl_fiber_schedule_with(__event_type);
acl_fiber_mutex_free(l);
}
//////////////////////////////////////////////////////////////////////////////
static int __event_type = FIBER_EVENT_KERNEL;
static int __use_yield = 0;
static int __use_event = 0;
static ACL_FIBER_MUTEX **__locks;
@ -58,6 +58,8 @@ static void fiber_main2(ACL_FIBER *fiber acl_unused, void *ctx acl_unused)
int i, ret;
ACL_FIBER_MUTEX *l;
printf("thread-%lu, fiber-%d start!\r\n", (long) pthread_self(), acl_fiber_self());
for (i = 0; i < __nloop; i++) {
l = __locks[i % __nlocks];
ret = acl_fiber_mutex_lock(l);
@ -66,7 +68,11 @@ static void fiber_main2(ACL_FIBER *fiber acl_unused, void *ctx acl_unused)
assert(ret == 0);
}
//acl_fiber_delay(100);
ret = acl_fiber_mutex_unlock(l);
//printf(">>fiber-%d unlock\n", acl_fiber_self());
if (ret) {
printf("%s: unlock error=%s\r\n", __FUNCTION__, strerror(ret));
assert(ret == 0);
@ -77,12 +83,14 @@ static void fiber_main2(ACL_FIBER *fiber acl_unused, void *ctx acl_unused)
acl_fiber_yield();
}
__count++;
//acl_fiber_delay(100);
}
if (--__nfibers == 0) {
printf("thread-%lu, all fibers over, count=%d!\r\n",
(unsigned long) pthread_self(), __count);
acl_fiber_schedule_stop();
printf("%s: thread-%lu, all fibers over, count=%d!\r\n",
__FUNCTION__, (unsigned long) pthread_self(), __count);
//acl_fiber_schedule_stop();
}
}
@ -103,8 +111,8 @@ static void fiber_main3(ACL_FIBER *fiber acl_unused, void *ctx acl_unused)
}
if (--__nfibers == 0) {
printf("thread-%lu, all fibers over, count=%d\r\n",
(unsigned long) pthread_self(), __count);
printf("%s: thread-%lu, all fibers over, count=%d\r\n",
__FUNCTION__, (unsigned long) pthread_self(), __count);
//acl_fiber_schedule_stop();
}
}
@ -168,10 +176,12 @@ static void test2(int nthreads, int nthreads2, unsigned flags)
for (i = 0; i < nthreads; i++) {
pthread_create(&threads[i], NULL, thread_main, NULL);
printf("--create fibers thread-%lu\r\n", (long) threads[i]);
}
for (i = 0; i < nthreads2; i++) {
pthread_create(&threads2[i], NULL, thread_alone_main, NULL);
printf("--create alone thread-%lu\r\n", (long) threads2[i]);
}
for (i = 0; i < nthreads; i++) {
@ -214,18 +224,50 @@ static void usage(const char *procname)
" -E [if use fiber_event]\r\n"
" -Y [if yield after unlock]\r\n"
" -T [if use first try lock for mutex]\r\n"
" -S [if using fiber switching first when they're in the same thread]\r\n"
, procname);
}
static void test_lock(void)
{
int i;
pthread_mutex_t lock;
pthread_mutex_init(&lock, NULL);
for (i = 0; i < 5; i++) {
int ret = pthread_mutex_trylock(&lock);
if (ret != 0) {
printf("lock error %s, i=%d\n", strerror(ret), i);
exit(1);
}
printf("lock ok, i=%d\n", i);
}
for (i = 0; i < 5; i++) {
int ret = pthread_mutex_lock(&lock);
if (ret != 0) {
printf("unlock error, i=%d\n", i);
exit(1);
}
printf("unlock ok, i=%d\n", i);
}
}
int main(int argc, char *argv[])
{
int ch, nthreads = 2, nthreads2 = 0;
unsigned flags = 0;
char action[64];
snprintf(action, sizeof(action), "test1");
if (0) {
test_lock();
}
while ((ch = getopt(argc, argv, "he:a:t:c:p:n:l:EYT")) > 0) {
snprintf(action, sizeof(action), "test2");
while ((ch = getopt(argc, argv, "he:a:t:c:p:n:l:EYTS")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
@ -266,6 +308,9 @@ int main(int argc, char *argv[])
case 'T':
flags |= FIBER_MUTEX_F_LOCK_TRY;
break;
case 'S':
flags |= FIBER_MUTEX_F_SWITCH_FIRST;
break;
default:
break;
}