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