1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include "event_notifier.h" 16 17#include <cerrno> 18#include <climits> 19#include <cstring> 20#include <fcntl.h> 21#include <sys/eventfd.h> 22#include <unistd.h> 23#include "logging.h" 24 25#ifndef EFD_SEMAPHORE 26#define EFD_SEMAPHORE 1 27#endif 28 29EventNotifierPtr EventNotifier::Create(unsigned int initValue, unsigned int mask) 30{ 31 return std::make_shared<EventNotifier>(initValue, mask); 32} 33 34EventNotifierPtr EventNotifier::CreateWithFd(int fd) 35{ 36 return std::make_shared<EventNotifier>(fd); 37} 38 39EventNotifier::EventNotifier(unsigned int initValue, unsigned int mask) : fd_(-1), flags_(O_CLOEXEC) 40{ 41 if (mask & NONBLOCK) { 42 flags_ |= O_NONBLOCK; 43 } 44 if (mask & SEMAPHORE) { 45 flags_ |= EFD_SEMAPHORE; 46 } 47 fd_ = eventfd(initValue, flags_); 48 CHECK_TRUE(fd_ >= 0, NO_RETVAL, "create eventfd FAILED, %d", errno); 49 PROFILER_LOG_DEBUG(LOG_CORE, "EventNotifier create eventfd %d done!", fd_); 50} 51 52EventNotifier::EventNotifier(int fd) : fd_(fd), flags_(0) 53{ 54 int flags = fcntl(fd_, F_GETFL); 55 CHECK_TRUE(flags >= 0, NO_RETVAL, "get flags of fd %d FAILED, %d", fd, errno); 56 PROFILER_LOG_DEBUG(LOG_CORE, "EventNotifier bind eventfd %d done!", fd_); 57} 58 59EventNotifier::~EventNotifier() 60{ 61 PROFILER_LOG_DEBUG(LOG_CORE, "EventNotifier close eventfd %d", fd_); 62 close(fd_); 63} 64 65int EventNotifier::GetFd() const 66{ 67 return fd_; 68} 69 70uint64_t EventNotifier::Take() const 71{ 72 uint64_t value = UINT64_MAX; 73 int retval = TEMP_FAILURE_RETRY(read(fd_, &value, sizeof(value))); 74 CHECK_TRUE(retval == sizeof(value), 0, "read value from eventfd %d failed, %d!", fd_, errno); 75 return value; 76} 77 78bool EventNotifier::Post(uint64_t value) const 79{ 80 int retval = TEMP_FAILURE_RETRY(write(fd_, &value, sizeof(value))); 81 CHECK_TRUE(retval == sizeof(value), false, "write value to eventfd %d failed, %d!", fd_, errno); 82 return true; 83} 84