1 /*
2 * Copyright (C) 2017 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 #ifndef INCLUDE_PERFETTO_BASE_UTILS_H_
18 #define INCLUDE_PERFETTO_BASE_UTILS_H_
19
20 #include "perfetto/base/build_config.h"
21
22 #include <errno.h>
23 #include <stddef.h>
24 #include <stdlib.h>
25 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
26 #include <sys/types.h>
27 #endif
28
29 #define PERFETTO_EINTR(x) \
30 ({ \
31 decltype(x) eintr_wrapper_result; \
32 do { \
33 eintr_wrapper_result = (x); \
34 } while (eintr_wrapper_result == -1 && errno == EINTR); \
35 eintr_wrapper_result; \
36 })
37
38 #define PERFETTO_LIKELY(_x) __builtin_expect(!!(_x), 1)
39 #define PERFETTO_UNLIKELY(_x) __builtin_expect(!!(_x), 0)
40
41 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
42 // TODO(brucedawson) - create a ::perfetto::base::IOSize to replace this.
43 #if defined(_WIN64)
44 using ssize_t = __int64;
45 #else
46 using ssize_t = long;
47 #endif
48 #endif
49
50 #if defined(__GNUC__) || defined(__clang__)
51 #define PERFETTO_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
52 #else
53 #define PERFETTO_WARN_UNUSED_RESULT
54 #endif
55
56 #if defined(__clang__)
57 #define PERFETTO_ALWAYS_INLINE __attribute__((__always_inline__))
58 #else
59 // GCC is too pedantic and often fails with the error:
60 // "always_inline function might not be inlinable"
61 #define PERFETTO_ALWAYS_INLINE
62 #endif
63
64 // TODO(lalitm): is_trivially_constructible is currently not available
65 // in some environments we build in. Reenable when that environment supports
66 // this.
67 #if defined(__GLIBCXX__)
68 #define PERFETTO_IS_TRIVIALLY_CONSTRUCTIBLE(T) true
69 #else
70 #define PERFETTO_IS_TRIVIALLY_CONSTRUCTIBLE(T) \
71 std::is_trivially_constructible<T>::value
72 #endif
73
74 // TODO(lalitm): is_trivially_copyable is currently not available
75 // in some environments we build in. Reenable when that environment supports
76 // this.
77 #if defined(__GLIBCXX__)
78 #define PERFETTO_IS_TRIVIALLY_COPYABLE(T) true
79 #else
80 #define PERFETTO_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
81 #endif
82
83 namespace perfetto {
84 namespace base {
85
86 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
87 constexpr uid_t kInvalidUid = static_cast<uid_t>(-1);
88 constexpr pid_t kInvalidPid = static_cast<pid_t>(-1);
89 #endif
90
91 constexpr size_t kPageSize = 4096;
92 constexpr size_t kMaxCpus = 128;
93
94 template <typename T>
ArraySize(const T & array)95 constexpr size_t ArraySize(const T& array) {
96 return sizeof(array) / sizeof(array[0]);
97 }
98
99 template <typename... T>
ignore_result(const T &...)100 inline void ignore_result(const T&...) {}
101
102 // Function object which invokes 'free' on its parameter, which must be
103 // a pointer. Can be used to store malloc-allocated pointers in std::unique_ptr:
104 //
105 // std::unique_ptr<int, base::FreeDeleter> foo_ptr(
106 // static_cast<int*>(malloc(sizeof(int))));
107 struct FreeDeleter {
operatorFreeDeleter108 inline void operator()(void* ptr) const { free(ptr); }
109 };
110
111 template <typename T>
AssumeLittleEndian(T value)112 constexpr T AssumeLittleEndian(T value) {
113 static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
114 "Unimplemented on big-endian archs");
115 return value;
116 }
117
118 // Round up |size| to a multiple of |alignment| (must be a power of two).
119 template <size_t alignment>
AlignUp(size_t size)120 constexpr size_t AlignUp(size_t size) {
121 static_assert((alignment & (alignment - 1)) == 0, "alignment must be a pow2");
122 return (size + alignment - 1) & ~(alignment - 1);
123 }
124
IsAgain(int err)125 inline bool IsAgain(int err) {
126 return err == EAGAIN || err == EWOULDBLOCK;
127 }
128
129 } // namespace base
130 } // namespace perfetto
131
132 #endif // INCLUDE_PERFETTO_BASE_UTILS_H_
133