mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-28 15:42:30 +00:00
MEDIUM: fd: Introduce a running mask, and use it instead of the spinlock.
In the struct fdtab, introduce a new mask, running_mask. Each thread should add its bit before using the fd. Use the running_mask instead of a lock, in fd_insert/fd_delete, we'll just spin as long as the mask is non-zero, to be sure we access the data exclusively. fd_set_running_excl() spins until the mask is 0, fd_set_running() just adds the thread bit, and fd_clr_running() removes it.
This commit is contained in:
parent
2ea1b49832
commit
a7bf573520
@ -529,7 +529,6 @@ static inline unsigned long thread_isolated()
|
|||||||
|
|
||||||
/* WARNING!!! if you update this enum, please also keep lock_label() up to date below */
|
/* WARNING!!! if you update this enum, please also keep lock_label() up to date below */
|
||||||
enum lock_label {
|
enum lock_label {
|
||||||
FD_LOCK,
|
|
||||||
TASK_RQ_LOCK,
|
TASK_RQ_LOCK,
|
||||||
TASK_WQ_LOCK,
|
TASK_WQ_LOCK,
|
||||||
POOL_LOCK,
|
POOL_LOCK,
|
||||||
@ -647,7 +646,6 @@ struct ha_rwlock {
|
|||||||
static inline const char *lock_label(enum lock_label label)
|
static inline const char *lock_label(enum lock_label label)
|
||||||
{
|
{
|
||||||
switch (label) {
|
switch (label) {
|
||||||
case FD_LOCK: return "FD";
|
|
||||||
case TASK_RQ_LOCK: return "TASK_RQ";
|
case TASK_RQ_LOCK: return "TASK_RQ";
|
||||||
case TASK_WQ_LOCK: return "TASK_WQ";
|
case TASK_WQ_LOCK: return "TASK_WQ";
|
||||||
case POOL_LOCK: return "POOL";
|
case POOL_LOCK: return "POOL";
|
||||||
|
@ -299,6 +299,23 @@ static inline void fd_want_send(int fd)
|
|||||||
updt_fd_polling(fd);
|
updt_fd_polling(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void fd_set_running(int fd)
|
||||||
|
{
|
||||||
|
_HA_ATOMIC_OR(&fdtab[fd].running_mask, tid_bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void fd_set_running_excl(int fd)
|
||||||
|
{
|
||||||
|
unsigned long old_mask = 0;
|
||||||
|
while (!_HA_ATOMIC_CAS(&fdtab[fd].running_mask, &old_mask, tid_bit));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void fd_clr_running(int fd)
|
||||||
|
{
|
||||||
|
_HA_ATOMIC_AND(&fdtab[fd].running_mask, ~tid_bit);
|
||||||
|
}
|
||||||
|
|
||||||
/* Update events seen for FD <fd> and its state if needed. This should be
|
/* Update events seen for FD <fd> and its state if needed. This should be
|
||||||
* called by the poller, passing FD_EV_*_{R,W,RW} in <evts>. FD_EV_ERR_*
|
* called by the poller, passing FD_EV_*_{R,W,RW} in <evts>. FD_EV_ERR_*
|
||||||
* doesn't need to also pass FD_EV_SHUT_*, it's implied. ERR and SHUT are
|
* doesn't need to also pass FD_EV_SHUT_*, it's implied. ERR and SHUT are
|
||||||
@ -353,8 +370,11 @@ static inline void fd_update_events(int fd, unsigned char evts)
|
|||||||
if (fdtab[fd].ev & (FD_POLL_OUT | FD_POLL_ERR))
|
if (fdtab[fd].ev & (FD_POLL_OUT | FD_POLL_ERR))
|
||||||
fd_may_send(fd);
|
fd_may_send(fd);
|
||||||
|
|
||||||
if (fdtab[fd].iocb && fd_active(fd))
|
if (fdtab[fd].iocb && fd_active(fd)) {
|
||||||
|
fd_set_running(fd);
|
||||||
fdtab[fd].iocb(fd);
|
fdtab[fd].iocb(fd);
|
||||||
|
fd_clr_running(fd);
|
||||||
|
}
|
||||||
|
|
||||||
/* we had to stop this FD and it still must be stopped after the I/O
|
/* we had to stop this FD and it still must be stopped after the I/O
|
||||||
* cb's changes, so let's program an update for this.
|
* cb's changes, so let's program an update for this.
|
||||||
@ -372,10 +392,10 @@ static inline void fd_update_events(int fd, unsigned char evts)
|
|||||||
/* Prepares <fd> for being polled */
|
/* Prepares <fd> for being polled */
|
||||||
static inline void fd_insert(int fd, void *owner, void (*iocb)(int fd), unsigned long thread_mask)
|
static inline void fd_insert(int fd, void *owner, void (*iocb)(int fd), unsigned long thread_mask)
|
||||||
{
|
{
|
||||||
unsigned long locked = atleast2(thread_mask);
|
int locked = fdtab[fd].running_mask != tid_bit;
|
||||||
|
|
||||||
if (locked)
|
if (locked)
|
||||||
HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
|
fd_set_running_excl(fd);
|
||||||
fdtab[fd].owner = owner;
|
fdtab[fd].owner = owner;
|
||||||
fdtab[fd].iocb = iocb;
|
fdtab[fd].iocb = iocb;
|
||||||
fdtab[fd].ev = 0;
|
fdtab[fd].ev = 0;
|
||||||
@ -386,7 +406,7 @@ static inline void fd_insert(int fd, void *owner, void (*iocb)(int fd), unsigned
|
|||||||
* still knows this FD from a possible previous round.
|
* still knows this FD from a possible previous round.
|
||||||
*/
|
*/
|
||||||
if (locked)
|
if (locked)
|
||||||
HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
|
fd_clr_running(fd);
|
||||||
/* the two directions are ready until proven otherwise */
|
/* the two directions are ready until proven otherwise */
|
||||||
fd_may_both(fd);
|
fd_may_both(fd);
|
||||||
_HA_ATOMIC_ADD(&ha_used_fds, 1);
|
_HA_ATOMIC_ADD(&ha_used_fds, 1);
|
||||||
|
@ -118,8 +118,8 @@ struct fdlist {
|
|||||||
|
|
||||||
/* info about one given fd */
|
/* info about one given fd */
|
||||||
struct fdtab {
|
struct fdtab {
|
||||||
__decl_hathreads(HA_SPINLOCK_T lock);
|
unsigned long running_mask; /* mask of thread IDs currntly using the fd */
|
||||||
unsigned long thread_mask; /* mask of thread IDs authorized to process the task */
|
unsigned long thread_mask; /* mask of thread IDs authorized to process the fd */
|
||||||
unsigned long update_mask; /* mask of thread IDs having an update for fd */
|
unsigned long update_mask; /* mask of thread IDs having an update for fd */
|
||||||
struct fdlist_entry update; /* Entry in the global update list */
|
struct fdlist_entry update; /* Entry in the global update list */
|
||||||
void (*iocb)(int fd); /* I/O handler */
|
void (*iocb)(int fd); /* I/O handler */
|
||||||
|
11
src/fd.c
11
src/fd.c
@ -300,10 +300,11 @@ done:
|
|||||||
*/
|
*/
|
||||||
static void fd_dodelete(int fd, int do_close)
|
static void fd_dodelete(int fd, int do_close)
|
||||||
{
|
{
|
||||||
unsigned long locked = atleast2(fdtab[fd].thread_mask);
|
int locked = fdtab[fd].running_mask != tid_bit;
|
||||||
|
|
||||||
if (locked)
|
if (locked)
|
||||||
HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
|
fd_set_running_excl(fd);
|
||||||
|
|
||||||
if (fdtab[fd].linger_risk) {
|
if (fdtab[fd].linger_risk) {
|
||||||
/* this is generally set when connecting to servers */
|
/* this is generally set when connecting to servers */
|
||||||
setsockopt(fd, SOL_SOCKET, SO_LINGER,
|
setsockopt(fd, SOL_SOCKET, SO_LINGER,
|
||||||
@ -324,7 +325,7 @@ static void fd_dodelete(int fd, int do_close)
|
|||||||
_HA_ATOMIC_SUB(&ha_used_fds, 1);
|
_HA_ATOMIC_SUB(&ha_used_fds, 1);
|
||||||
}
|
}
|
||||||
if (locked)
|
if (locked)
|
||||||
HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
|
fd_clr_running(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an FD from the fdsets.
|
/* Deletes an FD from the fdsets.
|
||||||
@ -602,7 +603,6 @@ int init_pollers()
|
|||||||
update_list.first = update_list.last = -1;
|
update_list.first = update_list.last = -1;
|
||||||
|
|
||||||
for (p = 0; p < global.maxsock; p++) {
|
for (p = 0; p < global.maxsock; p++) {
|
||||||
HA_SPIN_INIT(&fdtab[p].lock);
|
|
||||||
/* Mark the fd as out of the fd cache */
|
/* Mark the fd as out of the fd cache */
|
||||||
fdtab[p].update.next = -3;
|
fdtab[p].update.next = -3;
|
||||||
}
|
}
|
||||||
@ -639,9 +639,6 @@ void deinit_pollers() {
|
|||||||
struct poller *bp;
|
struct poller *bp;
|
||||||
int p;
|
int p;
|
||||||
|
|
||||||
for (p = 0; p < global.maxsock; p++)
|
|
||||||
HA_SPIN_DESTROY(&fdtab[p].lock);
|
|
||||||
|
|
||||||
for (p = 0; p < nbpollers; p++) {
|
for (p = 0; p < nbpollers; p++) {
|
||||||
bp = &pollers[p];
|
bp = &pollers[p];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user