1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdint.h> 18 #include <unistd.h> 19 20 #include "perfetto/base/event.h" 21 #include "perfetto/base/logging.h" 22 #include "perfetto/base/pipe.h" 23 24 #if PERFETTO_USE_EVENTFD() 25 #include <sys/eventfd.h> 26 #endif 27 28 namespace perfetto { 29 namespace base { 30 31 Event::Event() { 32 #if PERFETTO_USE_EVENTFD() 33 fd_.reset(eventfd(/* start value */ 0, EFD_CLOEXEC | EFD_NONBLOCK)); 34 PERFETTO_CHECK(fd_); 35 #else 36 // Make the pipe non-blocking so that we never block the waking thread (either 37 // the main thread or another one) when scheduling a wake-up. 38 Pipe pipe = Pipe::Create(Pipe::kBothNonBlock); 39 fd_ = std::move(pipe.rd); 40 write_fd_ = std::move(pipe.wr); 41 #endif // !PERFETTO_USE_EVENTFD() 42 } 43 44 Event::~Event() = default; 45 46 void Event::Notify() { 47 const uint64_t value = 1; 48 49 #if PERFETTO_USE_EVENTFD() 50 ssize_t ret = write(fd_.get(), &value, sizeof(value)); 51 #else 52 ssize_t ret = write(write_fd_.get(), &value, sizeof(uint8_t)); 53 #endif 54 55 if (ret <= 0 && errno != EAGAIN) { 56 PERFETTO_DFATAL("write()"); 57 } 58 } 59 60 void Event::Clear() { 61 #if PERFETTO_USE_EVENTFD() 62 uint64_t value; 63 ssize_t ret = read(fd_.get(), &value, sizeof(value)); 64 #else 65 // Drain the byte(s) written to the wake-up pipe. We can potentially read 66 // more than one byte if several wake-ups have been scheduled. 67 char buffer[16]; 68 ssize_t ret = read(fd_.get(), &buffer[0], sizeof(buffer)); 69 #endif 70 if (ret <= 0 && errno != EAGAIN) 71 PERFETTO_DPLOG("read()"); 72 } 73 74 } // namespace base 75 } // namespace perfetto 76