Blame src/vma/util/wakeup_pipe.cpp

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
}