io_channel: Add mechanism to call a function on each channel
For a given I/O device, call a user function on the correct thread for each channel. Change-Id: I568a443184ac834c80c5e36b80aa9b6f8bb0ac99 Signed-off-by: Ben Walker <benjamin.walker@intel.com> Reviewed-on: https://review.gerrithub.io/362256 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
a30ffb986e
commit
ff87d29cc3
@ -52,6 +52,10 @@ typedef void (*spdk_thread_pass_msg)(spdk_thread_fn fn, void *ctx,
|
|||||||
typedef int (*spdk_io_channel_create_cb)(void *io_device, void *ctx_buf);
|
typedef int (*spdk_io_channel_create_cb)(void *io_device, void *ctx_buf);
|
||||||
typedef void (*spdk_io_channel_destroy_cb)(void *io_device, void *ctx_buf);
|
typedef void (*spdk_io_channel_destroy_cb)(void *io_device, void *ctx_buf);
|
||||||
|
|
||||||
|
typedef void (*spdk_channel_msg)(void *io_device, struct spdk_io_channel *ch,
|
||||||
|
void *ctx);
|
||||||
|
typedef void (*spdk_channel_for_each_cpl)(void *io_device, void *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Initializes the calling thread for I/O channel allocation.
|
* \brief Initializes the calling thread for I/O channel allocation.
|
||||||
*
|
*
|
||||||
@ -136,4 +140,17 @@ void spdk_put_io_channel(struct spdk_io_channel *ch);
|
|||||||
*/
|
*/
|
||||||
void *spdk_io_channel_get_ctx(struct spdk_io_channel *ch);
|
void *spdk_io_channel_get_ctx(struct spdk_io_channel *ch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Call 'fn' on each channel associated with io_device. This happens
|
||||||
|
* asynchronously, so fn may be called after spdk_for_each_channel returns.
|
||||||
|
* 'fn' will be called on the correct thread for each channel. 'fn' will be
|
||||||
|
* called for each channel serially, such that two calls to 'fn' will not
|
||||||
|
* overlap in time.
|
||||||
|
*
|
||||||
|
* Once 'fn' has been called on each channel, 'cpl' will be called
|
||||||
|
* on the thread that spdk_for_each_channel was initially called from.
|
||||||
|
*/
|
||||||
|
void spdk_for_each_channel(void *io_device, spdk_channel_msg fn, void *ctx,
|
||||||
|
spdk_channel_for_each_cpl cpl);
|
||||||
|
|
||||||
#endif /* SPDK_IO_CHANNEL_H_ */
|
#endif /* SPDK_IO_CHANNEL_H_ */
|
||||||
|
@ -295,3 +295,89 @@ spdk_io_channel_get_ctx(struct spdk_io_channel *ch)
|
|||||||
{
|
{
|
||||||
return (uint8_t *)ch + sizeof(*ch);
|
return (uint8_t *)ch + sizeof(*ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct call_channel {
|
||||||
|
void *io_device;
|
||||||
|
spdk_channel_msg fn;
|
||||||
|
void *ctx;
|
||||||
|
|
||||||
|
struct spdk_thread *cur_thread;
|
||||||
|
struct spdk_io_channel *cur_ch;
|
||||||
|
|
||||||
|
struct spdk_thread *orig_thread;
|
||||||
|
spdk_channel_for_each_cpl cpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
_call_channel(void *ctx)
|
||||||
|
{
|
||||||
|
struct call_channel *ch_ctx = ctx;
|
||||||
|
struct spdk_thread *thread;
|
||||||
|
struct spdk_io_channel *ch;
|
||||||
|
|
||||||
|
thread = ch_ctx->cur_thread;
|
||||||
|
ch = ch_ctx->cur_ch;
|
||||||
|
|
||||||
|
ch_ctx->fn(ch_ctx->io_device, ch, ch_ctx->ctx);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&g_devlist_mutex);
|
||||||
|
thread = TAILQ_NEXT(thread, tailq);
|
||||||
|
while (thread) {
|
||||||
|
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
||||||
|
if (ch->io_device == ch_ctx->io_device) {
|
||||||
|
ch_ctx->cur_thread = thread;
|
||||||
|
ch_ctx->cur_ch = ch;
|
||||||
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
spdk_thread_send_msg(thread, _call_channel, ch_ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thread = TAILQ_NEXT(thread, tailq);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
|
||||||
|
ch_ctx->cpl(ch_ctx->io_device, ch_ctx->ctx);
|
||||||
|
free(ch_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spdk_for_each_channel(void *io_device, spdk_channel_msg fn, void *ctx,
|
||||||
|
spdk_channel_for_each_cpl cpl)
|
||||||
|
{
|
||||||
|
struct spdk_thread *thread;
|
||||||
|
struct spdk_io_channel *ch;
|
||||||
|
struct call_channel *ch_ctx;
|
||||||
|
|
||||||
|
ch_ctx = calloc(1, sizeof(*ch_ctx));
|
||||||
|
if (!ch_ctx) {
|
||||||
|
SPDK_ERRLOG("Unable to allocate context\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch_ctx->io_device = io_device;
|
||||||
|
ch_ctx->fn = fn;
|
||||||
|
ch_ctx->ctx = ctx;
|
||||||
|
ch_ctx->cpl = cpl;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&g_devlist_mutex);
|
||||||
|
ch_ctx->orig_thread = _get_thread();
|
||||||
|
|
||||||
|
TAILQ_FOREACH(thread, &g_threads, tailq) {
|
||||||
|
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
||||||
|
if (ch->io_device == io_device) {
|
||||||
|
ch_ctx->cur_thread = thread;
|
||||||
|
ch_ctx->cur_ch = ch;
|
||||||
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
spdk_thread_send_msg(thread, _call_channel, ch_ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ch_ctx);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
|
||||||
|
cpl(io_device, ctx);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user