\### After
```
0000000000e58600 <PeeringState::clear_blocked_outgoing()>:
e58600: 48 83 ec 18 sub $0x18,%rsp
e58604: 48 83 bf e0 00 00 00 cmpq $0x0,0xe0(%rdi)
e5860b: 00
e5860c: 0f 84 fc 0f b0 ff je 95960e <PeeringState::clear_blocked_outgoing() [clone .cold]+0x14>
e58612: 80 bf 40 01 00 00 00 cmpb $0x0,0x140(%rdi)
e58619: 0f 84 db 0f b0 ff je 9595fa <PeeringState::clear_blocked_outgoing() [clone .cold]>
e5861f: 80 bf 18 01 00 00 00 cmpb $0x0,0x118(%rdi)
e58626: 75 08 jne e58630 <PeeringState::clear_blocked_outgoing()+0x30>
e58628: 48 83 c4 18 add $0x18,%rsp
e5862c: c3 retq
e5862d: 0f 1f 00 nopl (%rax)
e58630: c6 87 18 01 00 00 00 movb $0x0,0x118(%rdi)
e58637: 48 8b bf f8 00 00 00 mov 0xf8(%rdi),%rdi
e5863e: 48 83 c4 18 add $0x18,%rsp
e58642: e9 89 bc ff ff jmpq e542d0 <std::_Rb_tree<int, std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > >, std::_Select1st<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > >, std::less<int>, std::allocator<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > >*) [clone .isra.0]>
e58647: 90 nop
e58648: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
e5864f: 00
```
\### Vanilla main
Loading of `assert_data_ctx` was `unlikely` bot not `cold`:
```
0000000000e3cf90 <PeeringState::clear_blocked_outgoing()>:
e3cf90: 48 83 ec 08 sub $0x8,%rsp
e3cf94: 48 83 bf e0 00 00 00 cmpq $0x0,0xe0(%rdi)
e3cf9b: 00
e3cf9c: 74 3d je e3cfdb <PeeringState::clear_blocked_outgoing()+0x4b>
e3cf9e: 80 bf 40 01 00 00 00 cmpb $0x0,0x140(%rdi)
e3cfa5: 74 28 je e3cfcf <PeeringState::clear_blocked_outgoing()+0x3f>
e3cfa7: 80 bf 18 01 00 00 00 cmpb $0x0,0x118(%rdi)
e3cfae: 75 08 jne e3cfb8 <PeeringState::clear_blocked_outgoing()+0x28>
e3cfb0: 48 83 c4 08 add $0x8,%rsp
e3cfb4: c3 retq
e3cfb5: 0f 1f 00 nopl (%rax)
e3cfb8: c6 87 18 01 00 00 00 movb $0x0,0x118(%rdi)
e3cfbf: 48 8b bf f8 00 00 00 mov 0xf8(%rdi),%rdi
e3cfc6: 48 83 c4 08 add $0x8,%rsp
e3cfca: e9 01 bd ff ff jmpq e38cd0 <std::_Rb_tree<int, std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > >, std::_Select1st<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > >, std::less<int>, std::allocator<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > >*) [clone .isra.0]>
e3cfcf: 48 8d 3d aa 0b 29 01 lea 0x1290baa(%rip),%rdi #
20cdb80 <PeeringState::clear_blocked_outgoing()::assert_data_ctx>
e3cfd6: e8 64 6c b6 ff callq 9a3c3f <ceph::__ceph_assert_fail(ceph::assert_data const&)>
e3cfdb: 48 8d 3d be 0b 29 01 lea 0x1290bbe(%rip),%rdi #
20cdba0 <PeeringState::clear_blocked_outgoing()::assert_data_ctx>
e3cfe2: e8 58 6c b6 ff callq 9a3c3f <ceph::__ceph_assert_fail(ceph::assert_data const&)>
e3cfe7: 90 nop
e3cfe8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
e3cfef: 00
```
Fixes: https://tracker.ceph.com/issues/70476
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
extern void __ceph_assert_fail(const char *assertion, const char *file, int line, const char *function);
extern void __ceph_assert_fail(const assert_data &ctx);
+template <const assert_data* AssertCtxV>
+[[gnu::noinline, gnu::cold]] static void __ceph_assert_fail() {
+ __ceph_assert_fail(*AssertCtxV);
+}
extern void __ceph_assertf_fail(const char *assertion, const char *file, int line, const char *function, const char* msg, ...);
extern void __ceph_assert_warn(const char *assertion, const char *file, int line, const char *function);
} while (false)
#else
#define ceph_assert(expr) \
- do { static const ceph::assert_data assert_data_ctx = \
- {__STRING(expr), __FILE__, __LINE__, __CEPH_ASSERT_FUNCTION}; \
- ((expr) \
- ? _CEPH_ASSERT_VOID_CAST (0) \
- : ::ceph::__ceph_assert_fail(assert_data_ctx)); } while(false)
+ do { \
+ static const auto func_name = __CEPH_ASSERT_FUNCTION; \
+ [] (const bool eval) { \
+ static const ceph::assert_data assert_data_ctx = \
+ {__STRING(expr), __FILE__, __LINE__, func_name}; \
+ ((eval) \
+ ? _CEPH_ASSERT_VOID_CAST (0) \
+ : ::ceph::__ceph_assert_fail<&assert_data_ctx>()); }((bool)(expr)); } while(false)
#endif
// this variant will *never* get compiled out to NDEBUG in the future.
} while(false)
#else
#define ceph_assert_always(expr) \
- do { static const ceph::assert_data assert_data_ctx = \
- {__STRING(expr), __FILE__, __LINE__, __CEPH_ASSERT_FUNCTION}; \
- ((expr) \
- ? _CEPH_ASSERT_VOID_CAST (0) \
- : ::ceph::__ceph_assert_fail(assert_data_ctx)); } while(false)
+ do { \
+ static const auto func_name = __CEPH_ASSERT_FUNCTION; \
+ [] (const bool eval) { \
+ static const ceph::assert_data assert_data_ctx = \
+ {__STRING(expr), __FILE__, __LINE__, func_name}; \
+ ((eval) \
+ ? _CEPH_ASSERT_VOID_CAST (0) \
+ : ::ceph::__ceph_assert_fail<&assert_data_ctx>()); }((bool)(expr)); } while(false)
#endif
// Named by analogy with printf. Along with an expression, takes a format