Optimize setsockopt for setting IO timeout in fiber.

This commit is contained in:
zhengshuxin 2024-03-25 17:48:01 +08:00
parent b0082d21bc
commit 1f7ad7098b
4 changed files with 56 additions and 12 deletions

View File

@ -199,6 +199,9 @@ struct FILE_EVENT {
#define EVENT_SENDMSG (unsigned) (1 << 28)
#endif // HAS_IO_URING
#define EVENT_SO_RCVTIMEO (unsigned) (1 << 29)
#define EVENT_SO_SNDTIMEO (unsigned) (1 << 30)
event_proc *r_proc;
event_proc *w_proc;
#ifdef HAS_POLL
@ -230,7 +233,7 @@ struct FILE_EVENT {
int flags;
} recv_ctx;
#if defined(IO_URING_HAS_RECVFROM)
# if defined(IO_URING_HAS_RECVFROM)
struct {
char *buf;
unsigned len;
@ -238,7 +241,7 @@ struct FILE_EVENT {
struct sockaddr *src_addr;
socklen_t *addrlen;
} recvfrom_ctx;
#endif
# endif
struct {
struct msghdr *msg;
@ -265,7 +268,7 @@ struct FILE_EVENT {
int flags;
} send_ctx;
#if defined(IO_URING_HAS_SENDTO)
# if defined(IO_URING_HAS_SENDTO)
struct {
const void *buf;
unsigned len;
@ -273,7 +276,7 @@ struct FILE_EVENT {
const struct sockaddr *dest_addr;
socklen_t addrlen;
} sendto_ctx;
#endif
# endif
struct {
const struct msghdr *msg;
@ -287,9 +290,9 @@ struct FILE_EVENT {
socklen_t len;
} peer;
#ifdef HAS_STATX
# ifdef HAS_STATX
struct statx *statxbuf;
#endif
# endif
char *path;
} var;
@ -297,11 +300,12 @@ struct FILE_EVENT {
struct IO_URING_CTX writer_ctx;
struct __kernel_timespec rts;
struct __kernel_timespec wts;
#endif // HAS_IO_URING
int r_timeout;
int w_timeout;
#endif
ACL_FIBER_SEM* mbox_wsem; // Used in sync_waiter_wakeup.c
#ifdef HAS_IOCP
@ -322,7 +326,8 @@ struct FILE_EVENT {
socklen_t len;
} peer;
} var;
#endif
#endif // HAS_IOCP
short refer;
short busy;
#define EVENT_BUSY_NONE (0)

View File

@ -179,7 +179,7 @@ void fiber_timer_add(ACL_FIBER *fiber, size_t milliseconds)
TIMER_CACHE_NODE *timer;
fiber->when = now + milliseconds;
ring_detach(&fiber->me);
ring_detach(&fiber->me); // Detch the previous binding.
timer_cache_add(__thread_fiber->ev_timer, fiber->when, &fiber->me);
/* Compute the event waiting interval according the timers' head */
@ -485,6 +485,10 @@ int fiber_wait_read(FILE_EVENT *fe)
WAITER_INC(__thread_fiber->event);
}
if (fe->mask & EVENT_SO_RCVTIMEO && fe->r_timeout > 0) {
fiber_timer_add(curr, fe->r_timeout);
}
acl_fiber_switch();
fe->fiber_r->wstatus &= ~FIBER_WAIT_READ;
@ -503,6 +507,7 @@ int fiber_wait_read(FILE_EVENT *fe)
return -1;
} else if (curr->flag & FIBER_F_TIMER) {
// If the IO reading timeout set in setsockopt.
// Clear FIBER_F_TIMER flag been set in wakeup_timers.
curr->flag &= ~FIBER_F_TIMER;
event_del_read(__thread_fiber->event, fe);
@ -555,6 +560,11 @@ int fiber_wait_write(FILE_EVENT *fe)
WAITER_INC(__thread_fiber->event);
}
if (fe->mask & EVENT_SO_SNDTIMEO && fe->w_timeout > 0) {
fiber_timer_add(curr, fe->w_timeout);
}
acl_fiber_switch();
fe->fiber_w->wstatus &= ~FIBER_WAIT_WRITE;

View File

@ -31,9 +31,9 @@ void file_event_init(FILE_EVENT *fe, socket_t fd)
memset(&fe->var, 0, sizeof(fe->var));
memset(&fe->reader_ctx, 0, sizeof(fe->reader_ctx));
memset(&fe->writer_ctx, 0, sizeof(fe->writer_ctx));
#endif
fe->r_timeout = -1;
fe->w_timeout = -1;
#endif
#ifdef HAS_IOCP
fe->rbuf = NULL;

View File

@ -546,6 +546,9 @@ int setsockopt(int sockfd, int level, int optname,
size_t val;
#ifdef CREAT_TIMER_FIBER
TIMEOUT_CTX *ctx;
#else
FILE_EVENT *fe;
ACL_FIBER *curr;
#endif
const struct timeval *tm;
@ -607,8 +610,34 @@ int setsockopt(int sockfd, int level, int optname,
return -1;
}
#else
curr = acl_fiber_running();
fe = fiber_file_open(sockfd);
if (val <= 0) {
fiber_timer_del(curr);
if (optname == SO_RCVTIMEO) {
fe->mask &= ~EVENT_SO_RCVTIMEO;
fe->r_timeout = -1;
} else if (optname == SO_SNDTIMEO) {
fe->mask &= ~EVENT_SO_SNDTIMEO;
fe->w_timeout = -1;
}
return 0;
}
val *= 1000;
fiber_timer_add(acl_fiber_running(), val);
if (optname == SO_RCVTIMEO) {
fe->mask |= EVENT_SO_RCVTIMEO;
fe->r_timeout = val;
} else if (optname == SO_SNDTIMEO) {
fe->mask |= EVENT_SO_SNDTIMEO;
fe->w_timeout = val;
} else {
msg_fatal("%s: Invalid optname=%d", __FUNCTION__, optname);
}
// We just set the flags here, and the timer will be add in
// fiber_wait_read or fiber_wait_write.
return 0;
#endif
}