|
Packit |
6d2c1b |
/*
|
|
Packit |
6d2c1b |
* Copyright (c) 2001-2020 Mellanox Technologies, Ltd. All rights reserved.
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* This software is available to you under a choice of one of two
|
|
Packit |
6d2c1b |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit |
6d2c1b |
* General Public License (GPL) Version 2, available from the file
|
|
Packit |
6d2c1b |
* COPYING in the main directory of this source tree, or the
|
|
Packit |
6d2c1b |
* BSD license below:
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* Redistribution and use in source and binary forms, with or
|
|
Packit |
6d2c1b |
* without modification, are permitted provided that the following
|
|
Packit |
6d2c1b |
* conditions are met:
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* - Redistributions of source code must retain the above
|
|
Packit |
6d2c1b |
* copyright notice, this list of conditions and the following
|
|
Packit |
6d2c1b |
* disclaimer.
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* - Redistributions in binary form must reproduce the above
|
|
Packit |
6d2c1b |
* copyright notice, this list of conditions and the following
|
|
Packit |
6d2c1b |
* disclaimer in the documentation and/or other materials
|
|
Packit |
6d2c1b |
* provided with the distribution.
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
6d2c1b |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
6d2c1b |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
6d2c1b |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
6d2c1b |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
6d2c1b |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
6d2c1b |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
6d2c1b |
* SOFTWARE.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#include "utils/bullseye.h"
|
|
Packit |
6d2c1b |
#include "vlogger/vlogger.h"
|
|
Packit |
6d2c1b |
#include "wakeup_pipe.h"
|
|
Packit |
6d2c1b |
#include "vma/sock/sock-redirect.h"
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#define MODULE_NAME "wakeup_pipe"
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#define wkup_logpanic __log_info_panic
|
|
Packit |
6d2c1b |
#define wkup_logerr __log_info_err
|
|
Packit |
6d2c1b |
#define wkup_logwarn __log_info_warn
|
|
Packit |
6d2c1b |
#define wkup_loginfo __log_info_info
|
|
Packit |
6d2c1b |
#define wkup_logdbg __log_info_dbg
|
|
Packit |
6d2c1b |
#define wkup_logfunc __log_info_func
|
|
Packit |
6d2c1b |
#define wkup_logfuncall __log_info_funcall
|
|
Packit |
6d2c1b |
#define wkup_entry_dbg __log_entry_dbg
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#undef MODULE_HDR_INFO
|
|
Packit |
6d2c1b |
#define MODULE_HDR_INFO MODULE_NAME "[epfd=%d]:%d:%s() "
|
|
Packit |
6d2c1b |
#undef __INFO__
|
|
Packit |
6d2c1b |
#define __INFO__ m_epfd
|
|
Packit |
6d2c1b |
#define UNINIT_PIPE_FD (-1)
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
int wakeup_pipe::g_wakeup_pipes[2] = {UNINIT_PIPE_FD, UNINIT_PIPE_FD};
|
|
Packit |
6d2c1b |
atomic_t wakeup_pipe::ref_count = ATOMIC_INIT(0);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
wakeup_pipe::wakeup_pipe()
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
int ref = atomic_fetch_and_inc(&ref_count);
|
|
Packit |
6d2c1b |
if (ref == 0) {
|
|
Packit |
6d2c1b |
BULLSEYE_EXCLUDE_BLOCK_START
|
|
Packit |
6d2c1b |
if (orig_os_api.pipe(g_wakeup_pipes)) {
|
|
Packit |
6d2c1b |
wkup_logpanic("wakeup pipe create failed (errno=%d %m)", errno);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
if (orig_os_api.write(g_wakeup_pipes[1], "^", 1) != 1) {
|
|
Packit |
6d2c1b |
wkup_logpanic("wakeup pipe write failed(errno=%d %m)", errno);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
BULLSEYE_EXCLUDE_BLOCK_END
|
|
Packit |
6d2c1b |
wkup_logdbg("created wakeup pipe [RD=%d, WR=%d]", g_wakeup_pipes[0], g_wakeup_pipes[1]);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
// ToDo - these pipe should be closed at some point
|
|
Packit |
6d2c1b |
// orig_os_api.close(g_si_wakeup_pipes[1]);
|
|
Packit |
6d2c1b |
// orig_os_api.close(g_si_wakeup_pipes[0]);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
m_ev.events = EPOLLIN;
|
|
Packit |
6d2c1b |
m_ev.data.fd = g_wakeup_pipes[0];
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
void wakeup_pipe::do_wakeup()
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
wkup_logfuncall("");
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
//m_wakeup_lock.lock();
|
|
Packit |
6d2c1b |
//This func should be called under socket / epoll lock
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
//Call to wakeup only in case there is some thread that is sleeping on epoll
|
|
Packit |
6d2c1b |
if (!m_is_sleeping)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
wkup_logfunc("There is no thread in epoll_wait, therefore not calling for wakeup");
|
|
Packit |
6d2c1b |
//m_wakeup_lock.unlock();
|
|
Packit |
6d2c1b |
return;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
wkup_entry_dbg("");
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
int errno_tmp = errno; //don't let wakeup affect errno, as this can fail with EEXIST
|
|
Packit |
6d2c1b |
BULLSEYE_EXCLUDE_BLOCK_START
|
|
Packit |
6d2c1b |
if ((orig_os_api.epoll_ctl(m_epfd, EPOLL_CTL_ADD, g_wakeup_pipes[0], &m_ev)) && (errno != EEXIST)) {
|
|
Packit |
6d2c1b |
wkup_logerr("Failed to add wakeup fd to internal epfd (errno=%d %m)", errno);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
BULLSEYE_EXCLUDE_BLOCK_END
|
|
Packit |
6d2c1b |
errno = errno_tmp;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
//m_wakeup_lock.unlock();
|
|
Packit |
6d2c1b |
//sched_yield();
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
void wakeup_pipe::remove_wakeup_fd()
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
if (m_is_sleeping) return;
|
|
Packit |
6d2c1b |
wkup_entry_dbg("");
|
|
Packit |
6d2c1b |
int tmp_errno = errno;
|
|
Packit |
6d2c1b |
if (orig_os_api.epoll_ctl(m_epfd, EPOLL_CTL_DEL, g_wakeup_pipes[0], NULL))
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
BULLSEYE_EXCLUDE_BLOCK_START
|
|
Packit |
6d2c1b |
if (errno == ENOENT) {
|
|
Packit |
6d2c1b |
wkup_logdbg("Failed to delete global pipe from internal epfd it was already deleted");
|
|
Packit |
6d2c1b |
} else {
|
|
Packit |
6d2c1b |
wkup_logerr("failed to delete global pipe from internal epfd (errno=%d %m)", errno);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
BULLSEYE_EXCLUDE_BLOCK_END
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
errno = tmp_errno;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
wakeup_pipe::~wakeup_pipe()
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
int ref = atomic_fetch_and_dec(&ref_count);
|
|
Packit |
6d2c1b |
if (ref == 1) {
|
|
Packit |
6d2c1b |
close(g_wakeup_pipes[0]);
|
|
Packit |
6d2c1b |
close(g_wakeup_pipes[1]);
|
|
Packit |
6d2c1b |
g_wakeup_pipes[0] = UNINIT_PIPE_FD;
|
|
Packit |
6d2c1b |
g_wakeup_pipes[1] = UNINIT_PIPE_FD;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
}
|