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:
parent
7ae061d1ea
commit
2d52c6a15b
@ -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`
|
Removed the `config_file`, `max_delay_us`, `pci_whitelist`
|
||||||
and `pci_blacklist` members of struct `spdk_app_opts`.
|
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
|
### iscsi
|
||||||
|
|
||||||
A security vulnerability has been identified and fixed in the SPDK iSCSI target.
|
A security vulnerability has been identified and fixed in the SPDK iSCSI target.
|
||||||
|
@ -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);
|
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.
|
* Register a poller on the current thread.
|
||||||
*
|
*
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
spdk_thread_send_msg;
|
spdk_thread_send_msg;
|
||||||
spdk_thread_send_critical_msg;
|
spdk_thread_send_critical_msg;
|
||||||
spdk_for_each_thread;
|
spdk_for_each_thread;
|
||||||
|
spdk_thread_set_interrupt_mode;
|
||||||
spdk_poller_register;
|
spdk_poller_register;
|
||||||
spdk_poller_register_named;
|
spdk_poller_register_named;
|
||||||
spdk_poller_unregister;
|
spdk_poller_unregister;
|
||||||
|
@ -720,6 +720,7 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs, uint64_t now)
|
|||||||
{
|
{
|
||||||
struct spdk_thread *orig_thread;
|
struct spdk_thread *orig_thread;
|
||||||
int rc;
|
int rc;
|
||||||
|
uint64_t notify = 1;
|
||||||
|
|
||||||
orig_thread = _get_thread();
|
orig_thread = _get_thread();
|
||||||
tls_thread = 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)) {
|
if (spdk_likely(!thread->in_interrupt)) {
|
||||||
rc = thread_poll(thread, max_msgs, now);
|
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 {
|
} else {
|
||||||
/* Non-block wait on thread's fd_group */
|
/* Non-block wait on thread's fd_group */
|
||||||
rc = spdk_fd_group_wait(thread->fgrp, 0);
|
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, ¬ify, 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;
|
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)) {
|
if (spdk_unlikely(target_thread->in_interrupt)) {
|
||||||
rc = write(target_thread->msg_fd, ¬ify, sizeof(notify));
|
rc = write(target_thread->msg_fd, ¬ify, sizeof(notify));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
@ -1334,6 +1355,29 @@ spdk_for_each_thread(spdk_msg_fn fn, void *ctx, spdk_msg_fn cpl)
|
|||||||
assert(rc == 0);
|
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
|
void
|
||||||
spdk_io_device_register(void *io_device, spdk_io_channel_create_cb create_cb,
|
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,
|
spdk_io_channel_destroy_cb destroy_cb, uint32_t ctx_size,
|
||||||
|
Loading…
Reference in New Issue
Block a user