thread: add spdk_thread_set_interrupt_mode func

spdk_thread_set_interrupt_mode can get spdk_thread run
between intr and poll mode. It is only valid when thread
interrupt facility is enabled by
spdk_interrupt_mode_enable(). Currently, this function
is limited that no poller is registered to the spdk_thread.

Change-Id: Iba54accd5976beb6f6e155014903928ce2858e36
Signed-off-by: Liu Xiaodong <xiaodong.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6708
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Liu Xiaodong 2021-02-26 08:23:00 -05:00 committed by Tomasz Zawadzki
parent 7ae061d1ea
commit 2d52c6a15b
4 changed files with 61 additions and 0 deletions

View File

@ -48,6 +48,12 @@ Removed the `pci_whitelist`, `pci_blacklist` and `master_core` members of struct
Removed the `config_file`, `max_delay_us`, `pci_whitelist`
and `pci_blacklist` members of struct `spdk_app_opts`.
### thread
Added `spdk_thread_set_interrupt_mode` function in order to set present spdk_thead into
interrupt mode or back to poll mode. It is valid only when thread interrupt facility is
enabled by spdk_interrupt_mode_enable().
### iscsi
A security vulnerability has been identified and fixed in the SPDK iSCSI target.

View File

@ -513,6 +513,16 @@ int spdk_thread_send_critical_msg(struct spdk_thread *thread, spdk_msg_fn fn);
*/
void spdk_for_each_thread(spdk_msg_fn fn, void *ctx, spdk_msg_fn cpl);
/**
* Set current spdk_thread into interrupt mode or back to poll mode.
*
* Only valid when thread interrupt facility is enabled by
* spdk_interrupt_mode_enable().
*
* \param enable_interrupt Set interrupt mode for true, or poll mode for false
*/
void spdk_thread_set_interrupt_mode(bool enable_interrupt);
/**
* Register a poller on the current thread.
*

View File

@ -29,6 +29,7 @@
spdk_thread_send_msg;
spdk_thread_send_critical_msg;
spdk_for_each_thread;
spdk_thread_set_interrupt_mode;
spdk_poller_register;
spdk_poller_register_named;
spdk_poller_unregister;

View File

@ -720,6 +720,7 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs, uint64_t now)
{
struct spdk_thread *orig_thread;
int rc;
uint64_t notify = 1;
orig_thread = _get_thread();
tls_thread = thread;
@ -730,9 +731,25 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs, uint64_t now)
if (spdk_likely(!thread->in_interrupt)) {
rc = thread_poll(thread, max_msgs, now);
if (spdk_unlikely(thread->in_interrupt)) {
/* The thread transitioned to interrupt mode during the above poll.
* Poll it one more time in case that during the transition time
* there is msg received without notification.
*/
rc = thread_poll(thread, max_msgs, now);
}
} else {
/* Non-block wait on thread's fd_group */
rc = spdk_fd_group_wait(thread->fgrp, 0);
if (spdk_unlikely(!thread->in_interrupt)) {
/* The thread transitioned to poll mode in a msg during the above processing.
* Clear msg_fd since thread messages will be polled directly in poll mode.
*/
rc = read(thread->msg_fd, &notify, sizeof(notify));
if (rc < 0 && errno != EAGAIN) {
SPDK_ERRLOG("failed to acknowledge msg queue: %s.\n", spdk_strerror(errno));
}
}
}
@ -889,6 +906,10 @@ thread_send_msg_notification(const struct spdk_thread *target_thread)
return 0;
}
/* When each spdk_thread can switch between poll and interrupt mode dynamically,
* after sending thread msg, it is necessary to check whether target thread runs in
* interrupt mode and then decide whether do event notification.
*/
if (spdk_unlikely(target_thread->in_interrupt)) {
rc = write(target_thread->msg_fd, &notify, sizeof(notify));
if (rc < 0) {
@ -1334,6 +1355,29 @@ spdk_for_each_thread(spdk_msg_fn fn, void *ctx, spdk_msg_fn cpl)
assert(rc == 0);
}
void
spdk_thread_set_interrupt_mode(bool enable_interrupt)
{
struct spdk_thread *thread = _get_thread();
assert(thread);
assert(spdk_interrupt_mode_is_enabled());
if (thread->in_interrupt == enable_interrupt) {
return;
}
/* Currently, only spdk_thread without pollers can set interrupt mode.
* TODO: remove it after adding interrupt mode switch into poller.
*/
assert(TAILQ_EMPTY(&thread->timed_pollers));
assert(TAILQ_EMPTY(&thread->active_pollers));
assert(TAILQ_EMPTY(&thread->paused_pollers));
thread->in_interrupt = enable_interrupt;
return;
}
void
spdk_io_device_register(void *io_device, spdk_io_channel_create_cb create_cb,
spdk_io_channel_destroy_cb destroy_cb, uint32_t ctx_size,