Motr  M0
misc.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include "lib/types.h"
24 #include "lib/assert.h"
25 #include "lib/arith.h" /* M0_3WAY */
26 #include "lib/arith.h"
27 #include "lib/string.h" /* sscanf */
28 #include "lib/errno.h" /* EINVAL */
29 #include "lib/buf.h" /* m0_buf */
30 #include "lib/trace.h" /* M0_RC */
31 
32 void __dummy_function(void)
33 {
34 }
35 
36 /* No padding. */
37 M0_BASSERT(sizeof(struct m0_uint128) == 16);
38 
39 M0_INTERNAL bool m0_uint128_eq(const struct m0_uint128 *u0,
40  const struct m0_uint128 *u1)
41 {
42  return m0_uint128_cmp(u0, u1) == 0;
43 }
44 
45 M0_INTERNAL int m0_uint128_cmp(const struct m0_uint128 *u0,
46  const struct m0_uint128 *u1)
47 {
48  return M0_3WAY(u0->u_hi, u1->u_hi) ?: M0_3WAY(u0->u_lo, u1->u_lo);
49 }
50 
51 M0_INTERNAL int m0_uint128_sscanf(const char *s, struct m0_uint128 *u128)
52 {
53  int rc = sscanf(s, U128I_F, U128_S(u128));
54 
55  if (rc < 2 || u128->u_hi == LLONG_MAX || u128->u_lo == LLONG_MAX)
56  /* fallback to hex format */
57  rc = sscanf(s, U128X_F, U128_S(u128));
58 
59  return rc == 2 ? 0 : -EINVAL;
60 }
61 
62 M0_INTERNAL void m0_uint128_add(struct m0_uint128 *res,
63  const struct m0_uint128 *a,
64  const struct m0_uint128 *b)
65 {
66  /*
67  * If res == a, we need to store the original value of a->u_lo
68  * in order for the function to work correctly.
69  */
70  uint64_t a_lo = a->u_lo;
71 
72  res->u_lo = a->u_lo + b->u_lo;
73  res->u_hi = a->u_hi + b->u_hi + (res->u_lo < a_lo);
74 }
75 
76 M0_INTERNAL void m0_uint128_mul64(struct m0_uint128 *res, uint64_t a,
77  uint64_t b)
78 {
79  uint64_t a_lo = a & UINT32_MAX;
80  uint64_t a_hi = a >> 32;
81  uint64_t b_lo = b & UINT32_MAX;
82  uint64_t b_hi = b >> 32;
83  uint64_t c;
84 
85  M0_CASSERT((sizeof a) * CHAR_BIT == 64);
86 
87  /*
88  * a * b = a_hi * b_hi * (1 << 64) +
89  * a_lo * b_lo +
90  * a_lo * b_hi * (1 << 32) +
91  * a_hi * b_lo * (1 << 32)
92  */
93  *res = M0_UINT128(a_hi * b_hi, a_lo * b_lo);
94  c = a_lo * b_hi;
95  m0_uint128_add(res, res, &M0_UINT128(c >> 32, (c & UINT32_MAX) << 32));
96  c = a_hi * b_lo;
97  m0_uint128_add(res, res, &M0_UINT128(c >> 32, (c & UINT32_MAX) << 32));
98 }
99 
100 uint64_t m0_rnd64(uint64_t *prev)
101 {
102  /*
103  * Linear congruential generator with constants from TAOCP MMIX.
104  * http://en.wikipedia.org/wiki/Linear_congruential_generator
105  */
106  /* double result; */
107  return *prev = *prev * 6364136223846793005ULL + 1442695040888963407ULL;
108  /*
109  * Use higher bits of *prev to generate return value, because they are
110  * more random.
111  */
112  /* return result * max / (1.0 + ~0ULL); */
113 }
114 
115 uint64_t m0_rnd(uint64_t max, uint64_t *prev)
116 {
117  uint64_t result;
118  /* Uses the same algorithm as GNU libc */
119  result = *prev = *prev * 0x5DEECE66DULL + 0xB;
120 
121  /* PRNG generates 48-bit values only */
122  M0_ASSERT((max >> 48) == 0);
123  /*Take value from higher 48 bits */
124  return (result >> 16) * max / ((~0UL) >> 16);
125 }
126 M0_EXPORTED(m0_rnd);
127 
128 M0_INTERNAL uint64_t m0_gcd64(uint64_t p, uint64_t q)
129 {
130  uint64_t t;
131 
132  while (q != 0) {
133  t = p % q;
134  p = q;
135  q = t;
136  }
137  return p;
138 }
139 
140 static uint64_t m0u64(const unsigned char *s)
141 {
142  uint64_t v;
143  int i;
144 
145  for (v = 0, i = 0; i < 8; ++i)
146  v |= ((uint64_t)s[i]) << (64 - 8 - i * 8);
147  return v;
148 }
149 
150 M0_INTERNAL void m0_uint128_init(struct m0_uint128 *u128, const char *magic)
151 {
152  M0_ASSERT(strlen(magic) == sizeof *u128);
153  u128->u_hi = m0u64((const unsigned char *)magic);
154  u128->u_lo = m0u64((const unsigned char *)magic + 8);
155 }
156 
157 enum {
159 };
160 
161 static int64_t getdelta(uint64_t x0, uint64_t x1)
162 {
163  int64_t delta;
164 
165  delta = (int64_t)x0 - (int64_t)x1;
166  M0_ASSERT( delta < (int64_t)M0_MOD_SAFE_LIMIT &&
167  -delta < (int64_t)M0_MOD_SAFE_LIMIT);
168  return delta;
169 }
170 
171 M0_INTERNAL bool m0_mod_gt(uint64_t x0, uint64_t x1)
172 {
173  return getdelta(x0, x1) > 0;
174 }
175 
176 M0_INTERNAL bool m0_mod_ge(uint64_t x0, uint64_t x1)
177 {
178  return getdelta(x0, x1) >= 0;
179 }
180 
181 M0_INTERNAL uint64_t m0_round_up(uint64_t val, uint64_t size)
182 {
184  return (val + size - 1) & ~(size - 1) ;
185 }
186 
187 M0_INTERNAL uint64_t m0_round_down(uint64_t val, uint64_t size)
188 {
190  return val & ~(size - 1);
191 }
192 
193 /*
194  * Check that ergo() and equi() macros are really what they pretend to be.
195  */
196 
197 M0_BASSERT(ergo(false, false) == true);
198 M0_BASSERT(ergo(false, true) == true);
199 M0_BASSERT(ergo(true, false) == false);
200 M0_BASSERT(ergo(true, true) == true);
201 
202 M0_BASSERT(equi(false, false) == true);
203 M0_BASSERT(equi(false, true) == false);
204 M0_BASSERT(equi(true, false) == false);
205 M0_BASSERT(equi(true, true) == true);
206 
207 M0_INTERNAL const char *m0_bool_to_str(bool b)
208 {
209  return b ? "true" : "false";
210 }
211 
212 M0_INTERNAL const char *m0_short_file_name(const char *fname)
213 {
214  static const char top_src_dir[] = "motr/";
215  const char *p;
216 
217  p = strstr(fname, top_src_dir);
218  if (p != NULL)
219  return p + strlen(top_src_dir);
220 
221  return fname;
222 }
223 
224 M0_INTERNAL const char *m0_failed_condition;
225 M0_EXPORTED(m0_failed_condition);
226 
227 M0_INTERNAL uint32_t m0_no_of_bits_set(uint64_t val)
228 {
229  uint32_t count = 0;
230  static const uint8_t bits_set[] = {
231  [ 0] = 0, /* 0000 */
232  [ 1] = 1, /* 0001 */
233  [ 2] = 1, /* 0010 */
234  [ 3] = 2, /* 0011 */
235  [ 4] = 1, /* 0100 */
236  [ 5] = 2, /* 0101 */
237  [ 6] = 2, /* 0110 */
238  [ 7] = 3, /* 0111 */
239  [ 8] = 1, /* 1000 */
240  [ 9] = 2, /* 1001 */
241  [10] = 2, /* 1010 */
242  [11] = 3, /* 1011 */
243  [12] = 2, /* 1100 */
244  [13] = 3, /* 1101 */
245  [14] = 3, /* 1110 */
246  [15] = 4 /* 1111 */
247  };
248 
249  while (val != 0) {
250  count += bits_set[val & 0xF];
251  val >>= 4;
252  }
253  return count;
254 }
255 
256 M0_INTERNAL bool
257 m0_elems_are_unique(const void *array, unsigned nr_elems, size_t elem_size)
258 {
259  return m0_forall(i, nr_elems,
260  m0_forall(j, i, memcmp(array + i * elem_size,
261  array + j * elem_size,
262  elem_size) != 0));
263 }
264 
265 M0_INTERNAL unsigned int
266 m0_full_name_hash(const unsigned char *name, unsigned int len)
267 {
268  unsigned long hash = 0;
269  unsigned long c;
270  while (len--) {
271  c = *name++;
272  hash = (hash + (c << 4) + (c >> 4)) * 11;
273  }
274  return ((unsigned int)hash);
275 }
276 
277 M0_INTERNAL uint64_t m0_ptr_wrap(const void *p)
278 {
279  return p != NULL ? p - (void *)&m0_ptr_wrap : 0;
280 }
281 
282 M0_INTERNAL const void *m0_ptr_unwrap(uint64_t val)
283 {
284  return val != 0 ? val + (void *)&m0_ptr_wrap : NULL;
285 }
286 
287 
288 M0_INTERNAL void m0_permute(uint64_t n, uint64_t *k, uint64_t *s, uint64_t *r)
289 {
290  uint64_t i;
291  uint64_t j;
292  uint64_t t;
293  uint64_t x;
294 
295  /*
296  * k[0] is an index of one of the n elements that permutation moves to
297  * the 0-th position in s[];
298  *
299  * k[1] is an index of one of the (n - 1) remaining elements that
300  * permutation moves to the 1-st position in s[], etc.
301  *
302  * To produce i-th element of s[], pick one of remaining elements, say
303  * s[t], as specified by k[i], shift elements s[i] ... s[t] to the right
304  * by one and place s[t] in s[i]. This guarantees that at beginning of
305  * the loop elements s[0] ... s[i - 1] are already selected and elements
306  * s[i] ... s[n - 1] are "remaining".
307  */
308 
309  for (i = 0; i < n - 1; ++i) {
310  t = k[i] + i;
311  M0_ASSERT(t < n);
312  x = s[t];
313  for (j = t; j > i; --j)
314  s[j] = s[j - 1];
315  s[i] = x;
316  r[x] = i;
317  }
318  /*
319  * The loop above iterates n-1 times, because the last element finds its
320  * place automatically. Complete inverse permutation.
321  */
322  r[s[n - 1]] = n - 1;
323 }
324 
325 M0_INTERNAL void m0_array_sort(uint64_t *arr, uint64_t arr_len)
326 {
327  uint64_t i;
328  uint64_t j;
329 
330  M0_PRE(arr_len > 0);
331  for (i = 0; i < arr_len - 1; ++i) {
332  for (j = i + 1; j < arr_len - 1; ++j) {
333  if (arr[i] > arr[j])
334  M0_SWAP(arr[i], arr[j]);
335  }
336  }
337 
338 }
339 
340 M0_INTERNAL bool m0_bit_get(void *buffer, m0_bcount_t i)
341 {
342  m0_bcount_t byte_num = M0_BYTES(i + 1) - 1;
343  char byte_val = *((char*)buffer + byte_num);
344  m0_bcount_t bit_shift = i % 8;
345 
346  return 0x1 & (byte_val >> bit_shift);
347 }
348 
349 M0_INTERNAL void m0_bit_set(void *buffer, m0_bcount_t i, bool val)
350 {
351  m0_bcount_t byte_num = M0_BYTES(i + 1) - 1;
352  m0_bcount_t bit_shift = i % 8;
353  char *byte_val = (char*)buffer + byte_num;
354 
355  *byte_val |= (0x1 & val) << bit_shift;
356 }
357 
358 M0_INTERNAL const struct m0_key_val M0_KEY_VAL_NULL = {
359  .kv_key = M0_BUF_INIT0,
360  .kv_val = M0_BUF_INIT0,
361 };
362 
363 M0_INTERNAL bool m0_key_val_is_null(struct m0_key_val *kv)
364 {
365  return m0_buf_eq(&M0_KEY_VAL_NULL.kv_key, &kv->kv_key) &&
367 }
368 
369 M0_INTERNAL void m0_key_val_init(struct m0_key_val *kv, const struct m0_buf *key,
370  const struct m0_buf *val)
371 {
372  M0_PRE(kv != NULL);
373 
374  kv->kv_key = *key;
375  kv->kv_val = *val;
376 }
377 
378 M0_INTERNAL void m0_key_val_null_set(struct m0_key_val *kv)
379 {
381 }
382 
383 M0_INTERNAL void *m0_vote_majority_get(struct m0_key_val *arr, uint32_t len,
384  bool (*cmp)(const struct m0_buf *,
385  const struct m0_buf *),
386  uint32_t *vote_nr)
387 {
388  struct m0_key_val null_kv = M0_KEY_VAL_NULL;
389  struct m0_key_val *mjr = &null_kv;
390  uint32_t i;
391  uint32_t count;
392 
393  for (i = 0, count = 0; i < len; ++i) {
394  if (count == 0)
395  mjr = &arr[i];
396  /* A M0_KEY_VAL_NULL requires a special handling. */
397  if (!m0_key_val_is_null(mjr) &&
398  !m0_key_val_is_null(&arr[i]))
399  /*
400  * A case when neither is M0_KEY_VAL_NULL, invoke
401  * a user provided comparison method
402  */
403  count += cmp(&mjr->kv_val, &arr[i].kv_val) ? 1: -1;
404  else if (m0_key_val_is_null(mjr) &&
405  m0_key_val_is_null(&arr[i]))
406  /* A case when both are M0_KEY_VAL_NULL. */
407  ++count;
408  else
409  /* Exactly one of the two is M0_KEY_VAL_NULL */
410  --count;
411  }
412  if (m0_key_val_is_null(mjr))
413  return NULL;
414  /* Check if the element found is present in majority. */
415  for (i = 0, count = 0; i < len; ++i) {
416  if (m0_key_val_is_null(&arr[i]))
417  continue;
418  if (cmp(&mjr->kv_val, &arr[i].kv_val))
419  ++count;
420  }
421  *vote_nr = count;
422  return count > len/2 ? mjr : NULL;
423 }
424 
425 M0_INTERNAL uint64_t m0_dummy_id_generate(void)
426 {
427  static struct m0_atomic64 counter = {};
428  return (uint64_t)m0_atomic64_add_return(&counter, 1);
429 }
430 
431 #if M0_RC_HOOK
432 M0_INTERNAL void m0_rc_hook(int rc)
433 {
434 }
435 
436 M0_INTERNAL void m0_err_hook(int rc)
437 {
438 }
439 #endif
440 
441 /*
442  * Local variables:
443  * c-indentation-style: "K&R"
444  * c-basic-offset: 8
445  * tab-width: 8
446  * fill-column: 80
447  * scroll-step: 1
448  * End:
449  */
M0_INTERNAL int m0_uint128_cmp(const struct m0_uint128 *u0, const struct m0_uint128 *u1)
Definition: misc.c:45
M0_INTERNAL void m0_key_val_null_set(struct m0_key_val *kv)
Definition: misc.c:378
static struct m0_addb2_philter p
Definition: consumer.c:40
#define U128I_F
Definition: types.h:44
#define M0_PRE(cond)
static struct m0_semaphore q
Definition: rwlock.c:55
#define NULL
Definition: misc.h:38
#define U128_S(u)
Definition: types.h:46
Definition: idx_mock.c:52
#define ergo(a, b)
Definition: misc.h:293
M0_INTERNAL bool m0_bit_get(void *buffer, m0_bcount_t i)
Definition: misc.c:340
#define M0_3WAY(v0, v1)
Definition: arith.h:199
static bool x
Definition: sm.c:168
M0_INTERNAL bool m0_buf_eq(const struct m0_buf *x, const struct m0_buf *y)
Definition: buf.c:90
M0_INTERNAL bool m0_uint128_eq(const struct m0_uint128 *u0, const struct m0_uint128 *u1)
Definition: misc.c:39
static int64_t getdelta(uint64_t x0, uint64_t x1)
Definition: misc.c:161
static uint64_t m0u64(const unsigned char *s)
Definition: misc.c:140
#define M0_CASSERT(cond)
M0_INTERNAL void m0_uint128_init(struct m0_uint128 *u128, const char *magic)
Definition: misc.c:150
static bool m0_is_po2(uint64_t val)
Definition: arith.h:153
M0_INTERNAL const char * m0_failed_condition
Definition: misc.c:224
static void m0_rc_hook(int rc)
Definition: trace.h:188
static uint64_t magic(const struct m0_tl_descr *d, const void *obj)
Definition: tlist.c:286
M0_INTERNAL void m0_permute(uint64_t n, uint64_t *k, uint64_t *s, uint64_t *r)
Definition: misc.c:288
uint64_t m0_bcount_t
Definition: types.h:77
M0_INTERNAL bool m0_mod_ge(uint64_t x0, uint64_t x1)
Definition: misc.c:176
M0_INTERNAL bool m0_elems_are_unique(const void *array, unsigned nr_elems, size_t elem_size)
Definition: misc.c:257
#define M0_SWAP(v0, v1)
Definition: arith.h:207
M0_INTERNAL const struct m0_key_val M0_KEY_VAL_NULL
Definition: misc.c:358
#define UINT32_MAX
Definition: types.h:41
static m0_bcount_t count
Definition: xcode.c:167
M0_INTERNAL uint64_t m0_round_up(uint64_t val, uint64_t size)
Definition: misc.c:181
M0_INTERNAL const char * m0_short_file_name(const char *fname)
Definition: misc.c:212
M0_INTERNAL uint64_t m0_round_down(uint64_t val, uint64_t size)
Definition: misc.c:187
#define equi(a, b)
Definition: misc.h:297
Definition: buf.h:37
M0_INTERNAL uint64_t m0_dummy_id_generate(void)
Definition: misc.c:425
int i
Definition: dir.c:1033
#define M0_BYTES(bits_nr)
Definition: misc.h:442
uint64_t m0_rnd(uint64_t max, uint64_t *prev)
Definition: misc.c:115
static int key
Definition: locality.c:283
const char * name
Definition: trace.c:110
#define M0_ASSERT(cond)
M0_INTERNAL const char * m0_bool_to_str(bool b)
Definition: misc.c:207
static struct m0_addb2_callback c
Definition: consumer.c:41
M0_INTERNAL void m0_key_val_init(struct m0_key_val *kv, const struct m0_buf *key, const struct m0_buf *val)
Definition: misc.c:369
static struct m0_thread t[8]
Definition: service_ut.c:1230
static int counter
Definition: mutex.c:32
static long long max(long long a, long long b)
Definition: crate.c:196
#define M0_BUF_INIT0
Definition: buf.h:71
uint64_t u_hi
Definition: types.h:57
M0_INTERNAL const void * m0_ptr_unwrap(uint64_t val)
Definition: misc.c:282
M0_INTERNAL uint32_t m0_no_of_bits_set(uint64_t val)
Definition: misc.c:227
uint64_t u_hi
Definition: types.h:36
static int cmp(const struct m0_ut_suite **s0, const struct m0_ut_suite **s1)
Definition: ut.c:654
#define UINT64_MAX
Definition: types.h:44
M0_INTERNAL uint64_t m0_gcd64(uint64_t p, uint64_t q)
Definition: misc.c:128
#define U128X_F
Definition: types.h:42
#define m0_forall(var, nr,...)
Definition: misc.h:112
M0_INTERNAL bool m0_mod_gt(uint64_t x0, uint64_t x1)
Definition: misc.c:171
uint64_t n
Definition: fops.h:107
uint64_t m0_rnd64(uint64_t *prev)
Definition: misc.c:100
struct m0_buf kv_val
Definition: misc.h:419
M0_INTERNAL void m0_uint128_mul64(struct m0_uint128 *res, uint64_t a, uint64_t b)
Definition: misc.c:76
M0_INTERNAL int m0_uint128_sscanf(const char *s, struct m0_uint128 *u128)
Definition: misc.c:51
struct m0_buf kv_key
Definition: misc.h:418
static int r[NR]
Definition: thread.c:46
Definition: addb2.c:200
m0_bcount_t size
Definition: di.c:39
M0_INTERNAL void m0_bit_set(void *buffer, m0_bcount_t i, bool val)
Definition: misc.c:349
M0_INTERNAL uint64_t m0_ptr_wrap(const void *p)
Definition: misc.c:277
#define M0_UINT128(hi, lo)
Definition: types.h:40
static void m0_err_hook(int rc)
Definition: trace.h:190
M0_BASSERT(sizeof(struct m0_uint128)==16)
void __dummy_function(void)
Definition: misc.c:32
M0_INTERNAL void m0_array_sort(uint64_t *arr, uint64_t arr_len)
Definition: misc.c:325
M0_INTERNAL void * m0_vote_majority_get(struct m0_key_val *arr, uint32_t len, bool(*cmp)(const struct m0_buf *, const struct m0_buf *), uint32_t *vote_nr)
Definition: misc.c:383
#define CHAR_BIT
Definition: misc.h:32
uint64_t u_lo
Definition: types.h:37
static struct m0_addb2_source * s
Definition: consumer.c:39
int32_t rc
Definition: trigger_fop.h:47
M0_INTERNAL unsigned int m0_full_name_hash(const unsigned char *name, unsigned int len)
Definition: misc.c:266
M0_INTERNAL bool m0_key_val_is_null(struct m0_key_val *kv)
Definition: misc.c:363
M0_INTERNAL void m0_uint128_add(struct m0_uint128 *res, const struct m0_uint128 *a, const struct m0_uint128 *b)
Definition: misc.c:62
static int64_t m0_atomic64_add_return(struct m0_atomic64 *a, int64_t d)
Definition: idx_mock.c:47