LCOV - code coverage report
Current view: top level - vppinfra - clib.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 30 33 90.9 %
Date: 2023-10-26 01:39:38 Functions: 11 12 91.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       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             : /*
      16             :   Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
      17             : 
      18             :   Permission is hereby granted, free of charge, to any person obtaining
      19             :   a copy of this software and associated documentation files (the
      20             :   "Software"), to deal in the Software without restriction, including
      21             :   without limitation the rights to use, copy, modify, merge, publish,
      22             :   distribute, sublicense, and/or sell copies of the Software, and to
      23             :   permit persons to whom the Software is furnished to do so, subject to
      24             :   the following conditions:
      25             : 
      26             :   The above copyright notice and this permission notice shall be
      27             :   included in all copies or substantial portions of the Software.
      28             : 
      29             :   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      30             :   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      31             :   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      32             :   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      33             :   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      34             :   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      35             :   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      36             : */
      37             : 
      38             : #ifndef included_clib_h
      39             : #define included_clib_h
      40             : 
      41             : #include <stddef.h>
      42             : 
      43             : #if __has_include(<vppinfra/config.h>)
      44             : #include <vppinfra/config.h>
      45             : #endif
      46             : 
      47             : #ifdef  __x86_64__
      48             : #include <x86intrin.h>
      49             : #endif
      50             : 
      51             : /* Standalone means to not assume we are running on a Unix box. */
      52             : #if ! defined (CLIB_STANDALONE) && ! defined (CLIB_LINUX_KERNEL)
      53             : #define CLIB_UNIX
      54             : #endif
      55             : 
      56             : #ifdef __linux__
      57             : #define CLIB_LINUX 1
      58             : #else
      59             : #define CLIB_LINUX 0
      60             : #endif
      61             : 
      62             : #include <vppinfra/types.h>
      63             : #include <vppinfra/atomics.h>
      64             : 
      65             : /* Global DEBUG flag.  Setting this to 1 or 0 turns off
      66             :    ASSERT (see vppinfra/error.h) & other debugging code. */
      67             : #ifndef CLIB_DEBUG
      68             : #define CLIB_DEBUG 0
      69             : #endif
      70             : 
      71             : #ifndef NULL
      72             : #define NULL ((void *) 0)
      73             : #endif
      74             : 
      75             : #define BITS(x)         (8*sizeof(x))
      76             : #define ARRAY_LEN(x)    (sizeof (x)/sizeof (x[0]))
      77             : #define FOREACH_ARRAY_ELT(a, b)                                               \
      78             :   for (typeof ((b)[0]) *(a) = (b); (a) - (b) < ARRAY_LEN (b); (a)++)
      79             : 
      80             : #define _STRUCT_FIELD(t,f) (((t *) 0)->f)
      81             : #define STRUCT_OFFSET_OF(t,f) offsetof(t, f)
      82             : #define STRUCT_BIT_OFFSET_OF(t,f) (BITS(u8) * STRUCT_OFFSET_OF (t, f))
      83             : #define STRUCT_SIZE_OF(t,f)   (sizeof (_STRUCT_FIELD (t, f)))
      84             : #define STRUCT_BITS_OF(t,f)   (BITS (_STRUCT_FIELD (t, f)))
      85             : #define STRUCT_ARRAY_LEN(t,f) ARRAY_LEN (_STRUCT_FIELD (t, f))
      86             : #define STRUCT_MARK(mark)     u8 mark[0]
      87             : #define STRUCT_MARK_PTR(v, f) &(v)->f
      88             : 
      89             : /* Stride in bytes between struct array elements. */
      90             : #define STRUCT_STRIDE_OF(t,f)                   \
      91             :   (  ((uword) & (((t *) 0)[1].f))           \
      92             :    - ((uword) & (((t *) 0)[0].f)))
      93             : 
      94             : #define STRUCT_OFFSET_OF_VAR(v,f) ((uword) (&(v)->f) - (uword) (v))
      95             : 
      96             : /* Used to pack structure elements. */
      97             : #define CLIB_PACKED(x)  x __attribute__ ((packed))
      98             : #define CLIB_UNUSED(x)  x __attribute__ ((unused))
      99             : 
     100             : /* similar to CLIB_CACHE_LINE_ALIGN_MARK() but with arbitrary alignment */
     101             : #define CLIB_ALIGN_MARK(name, alignment) u8 name[0] __attribute__((aligned(alignment)))
     102             : 
     103             : /* Make a string from the macro's argument */
     104             : #define CLIB_STRING_MACRO(x) #x
     105             : 
     106             : #define CLIB_STRING_ARRAY(...)                                                \
     107             :   (char *[]) { __VA_ARGS__, 0 }
     108             : 
     109             : /* sanitizers */
     110             : #ifdef __has_feature
     111             : #if __has_feature(address_sanitizer)
     112             : #define CLIB_SANITIZE_ADDR 1
     113             : #endif
     114             : #elif defined(__SANITIZE_ADDRESS__)
     115             : #define CLIB_SANITIZE_ADDR 1
     116             : #endif
     117             : 
     118             : #define __clib_unused __attribute__ ((unused))
     119             : #define __clib_weak __attribute__ ((weak))
     120             : #define __clib_packed __attribute__ ((packed))
     121             : #define __clib_flatten     __attribute__ ((flatten))
     122             : #define __clib_constructor __attribute__ ((constructor))
     123             : #define __clib_noinline __attribute__ ((noinline))
     124             : #ifdef __clang__
     125             : #define __clib_noclone
     126             : #else
     127             : #define __clib_noclone            __attribute__ ((noclone))
     128             : #endif
     129             : #define __clib_aligned(x) __attribute__ ((aligned(x)))
     130             : #define __clib_section(s) __attribute__ ((section(s)))
     131             : #define __clib_warn_unused_result __attribute__ ((warn_unused_result))
     132             : #define __clib_export __attribute__ ((visibility("default")))
     133             : #ifdef __clang__
     134             : #define __clib_no_tail_calls __attribute__ ((disable_tail_calls))
     135             : #else
     136             : #define __clib_no_tail_calls                                                  \
     137             :   __attribute__ ((optimize ("no-optimize-sibling-calls")))
     138             : #endif
     139             : 
     140             : #ifdef CLIB_SANITIZE_ADDR
     141             : #define __clib_nosanitize_addr __attribute__ ((no_sanitize_address))
     142             : #else
     143             : #define __clib_nosanitize_addr
     144             : #endif
     145             : 
     146             : #define never_inline __attribute__ ((__noinline__))
     147             : 
     148             : #if CLIB_DEBUG > 0
     149             : #define always_inline static inline
     150             : #define static_always_inline static inline
     151             : #else
     152             : #define always_inline static inline __attribute__ ((__always_inline__))
     153             : #define static_always_inline static inline __attribute__ ((__always_inline__))
     154             : #endif
     155             : 
     156             : 
     157             : /* Reserved (unused) structure element with address offset between
     158             :    from and to. */
     159             : #define CLIB_PAD_FROM_TO(from,to) u8 pad_##from[(to) - (from)]
     160             : 
     161             : /* Hints to compiler about hot/cold code. */
     162             : #define PREDICT_FALSE(x) __builtin_expect((x),0)
     163             : #define PREDICT_TRUE(x) __builtin_expect((x),1)
     164             : #define COMPILE_TIME_CONST(x) __builtin_constant_p (x)
     165             : #define CLIB_ASSUME(x)                                                        \
     166             :   do                                                                          \
     167             :     {                                                                         \
     168             :       if (!(x))                                                               \
     169             :         __builtin_unreachable ();                                             \
     170             :     }                                                                         \
     171             :   while (0)
     172             : 
     173             : /*
     174             :  * Compiler barrier
     175             :  *   prevent compiler to reorder memory access across this boundary
     176             :  *   prevent compiler to cache values in register (force reload)
     177             :  * Not to be confused with CPU memory barrier below
     178             :  */
     179             : #define CLIB_COMPILER_BARRIER() asm volatile ("":::"memory")
     180             : 
     181             : /* Full memory barrier (read and write). */
     182             : #define CLIB_MEMORY_BARRIER() __sync_synchronize ()
     183             : 
     184             : #if __SSE__
     185             : #define CLIB_MEMORY_STORE_BARRIER() __builtin_ia32_sfence ()
     186             : #else
     187             : #define CLIB_MEMORY_STORE_BARRIER() __sync_synchronize ()
     188             : #endif
     189             : 
     190             : /* Arranges for function to be called before main. */
     191             : #define INIT_FUNCTION(decl)                     \
     192             :   decl __attribute ((constructor));             \
     193             :   decl
     194             : 
     195             : /* Arranges for function to be called before exit. */
     196             : #define EXIT_FUNCTION(decl)                     \
     197             :   decl __attribute ((destructor));              \
     198             :   decl
     199             : 
     200             : always_inline uword
     201  1853182804 : pow2_mask (uword x)
     202             : {
     203             : #ifdef __BMI2__
     204   293914027 :   return _bzhi_u64 (-1ULL, x);
     205             : #endif
     206  1559268777 :   return ((uword) 1 << x) - (uword) 1;
     207             : }
     208             : 
     209             : #include <vppinfra/bitops.h>
     210             : 
     211             : always_inline uword
     212    54319166 : min_log2 (uword x)
     213             : {
     214             :   uword n;
     215    54319166 :   n = count_leading_zeros (x);
     216    54319166 :   return BITS (uword) - n - 1;
     217             : }
     218             : 
     219             : always_inline uword
     220     3093555 : max_log2 (uword x)
     221             : {
     222     3093555 :   uword l = min_log2 (x);
     223     3093556 :   if (x > ((uword) 1 << l))
     224      388217 :     l++;
     225     3093556 :   return l;
     226             : }
     227             : 
     228             : always_inline u64
     229        1889 : min_log2_u64 (u64 x)
     230             : {
     231             :   if (BITS (uword) == 64)
     232        1889 :     return min_log2 (x);
     233             :   else
     234             :     {
     235             :       uword l, y;
     236             :       y = x;
     237             :       l = 0;
     238             :       if (y == 0)
     239             :         {
     240             :           l += 32;
     241             :           x >>= 32;
     242             :         }
     243             :       l += min_log2 (x);
     244             :       return l;
     245             :     }
     246             : }
     247             : 
     248             : always_inline uword
     249       12037 : max_pow2 (uword x)
     250             : {
     251       12037 :   word y = (word) 1 << min_log2 (x);
     252       12037 :   if (x > y)
     253       11411 :     y *= 2;
     254       12037 :   return y;
     255             : }
     256             : 
     257             : always_inline uword
     258   822996045 : is_pow2 (uword x)
     259             : {
     260   822996045 :   return 0 == (x & (x - 1));
     261             : }
     262             : 
     263             : always_inline uword
     264      116667 : round_down_pow2 (uword x, uword pow2)
     265             : {
     266      116667 :   return (x) & ~(pow2 - 1);
     267             : }
     268             : 
     269             : always_inline uword
     270   296295386 : round_pow2 (uword x, uword pow2)
     271             : {
     272   296295386 :   return (x + pow2 - 1) & ~(pow2 - 1);
     273             : }
     274             : 
     275             : always_inline u64
     276        3480 : round_pow2_u64 (u64 x, u64 pow2)
     277             : {
     278        3480 :   return (x + pow2 - 1) & ~(pow2 - 1);
     279             : }
     280             : 
     281             : always_inline uword
     282           0 : first_set (uword x)
     283             : {
     284           0 :   return x & -x;
     285             : }
     286             : 
     287             : always_inline f64
     288             : flt_round_down (f64 x)
     289             : {
     290             :   return (int) x;
     291             : }
     292             : 
     293             : always_inline word
     294      290959 : flt_round_nearest (f64 x)
     295             : {
     296      290959 :   return (word) (x + .5);
     297             : }
     298             : 
     299             : always_inline f64
     300             : flt_round_to_multiple (f64 x, f64 f)
     301             : {
     302             :   return f * flt_round_nearest (x / f);
     303             : }
     304             : 
     305             : always_inline uword
     306        1154 : extract_bits (uword x, int start, int count)
     307             : {
     308             : #ifdef __BMI__
     309           0 :   return _bextr_u64 (x, start, count);
     310             : #endif
     311        1154 :   return (x >> start) & pow2_mask (count);
     312             : }
     313             : 
     314             : #define clib_max(x,y)                           \
     315             : ({                                              \
     316             :   __typeof__ (x) _x = (x);                      \
     317             :   __typeof__ (y) _y = (y);                      \
     318             :   _x > _y ? _x : _y;                         \
     319             : })
     320             : 
     321             : #define clib_min(x,y)                           \
     322             : ({                                              \
     323             :   __typeof__ (x) _x = (x);                      \
     324             :   __typeof__ (y) _y = (y);                      \
     325             :   _x < _y ? _x : _y;                         \
     326             : })
     327             : 
     328             : #define clib_clamp(x,lo,hi)                     \
     329             : ({                                              \
     330             :   __typeof__ (x) _x = (x);                      \
     331             :   __typeof__ (lo) _lo = (lo);                   \
     332             :   __typeof__ (hi) _hi = (hi);                   \
     333             :   _x < _lo ? _lo : (_x > _hi ? _hi : _x); \
     334             : })
     335             : 
     336             : #define clib_abs(x)                             \
     337             : ({                                              \
     338             :   __typeof__ (x) _x = (x);                      \
     339             :   _x < 0 ? -_x : _x;                         \
     340             : })
     341             : 
     342             : static_always_inline u64
     343             : u64_add_with_carry (u64 *carry, u64 a, u64 b)
     344             : {
     345             : #if defined(__x86_64__)
     346             :   unsigned long long v;
     347             :   *carry = _addcarry_u64 (*carry, a, b, &v);
     348             :   return (u64) v;
     349             : #elif defined(__clang__)
     350             :   unsigned long long c;
     351             :   u64 rv = __builtin_addcll (a, b, *carry, &c);
     352             :   *carry = c;
     353             :   return rv;
     354             : #else
     355             :   u64 rv = a + b + *carry;
     356             :   *carry = rv < a;
     357             :   return rv;
     358             : #endif
     359             : }
     360             : 
     361             : static_always_inline u64
     362             : u64_sub_with_borrow (u64 *borrow, u64 x, u64 y)
     363             : {
     364             : #if defined(__x86_64__)
     365             :   unsigned long long v;
     366             :   *borrow = _subborrow_u64 (*borrow, x, y, &v);
     367             :   return (u64) v;
     368             : #elif defined(__clang__)
     369             :   unsigned long long b;
     370             :   u64 rv = __builtin_subcll (x, y, *borrow, &b);
     371             :   *borrow = b;
     372             :   return rv;
     373             : #else
     374             :   unsigned long long rv = x - (y + *borrow);
     375             :   *borrow = rv >= x;
     376             :   return rv;
     377             : #endif
     378             : }
     379             : 
     380             : /* Standard standalone-only function declarations. */
     381             : #ifndef CLIB_UNIX
     382             : void clib_standalone_init (void *memory, uword memory_bytes);
     383             : 
     384             : void qsort (void *base, uword n, uword size,
     385             :             int (*)(const void *, const void *));
     386             : #endif
     387             : 
     388             : /* Stack backtrace. */
     389             : uword
     390             : clib_backtrace (uword * callers, uword max_callers, uword n_frames_to_skip);
     391             : 
     392             : #include <vppinfra/byte_order.h>
     393             : #endif /* included_clib_h */
     394             : 
     395             : /*
     396             :  * fd.io coding-style-patch-verification: ON
     397             :  *
     398             :  * Local Variables:
     399             :  * eval: (c-set-style "gnu")
     400             :  * End:
     401             :  */

Generated by: LCOV version 1.14