1/* 2 * Copyright 2017-2018, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5#ifndef _FBSD_COMPAT_SYS_COUNTER_H_ 6#define _FBSD_COMPAT_SYS_COUNTER_H_ 7 8#include <machine/atomic.h> 9#include <sys/malloc.h> 10 11 12/* FreeBSD does not use atomics: it has a per-CPU data storage structure 13 * that it adds to whenever someone calls add(), and then only locks and 14 * coalesces it whenever fetch() is called. This means that on some 15 * architectures (e.g. x86_64), adding to the counter is one instruction. 16 * 17 * However, this seems to be for the most part overengineering, as its 18 * only uses seem to be statistical counting in semi-performance-critical paths. 19 * Axel noted in #12328 that there's a potential way to implement FreeBSD's 20 * method on Haiku using cpu_ent, but that atomics were "perfectly fine", 21 * so we will go with that for now. 22 */ 23 24 25typedef uint64_t* counter_u64_t; 26 27 28static inline counter_u64_t 29counter_u64_alloc(int wait) 30{ 31 return (counter_u64_t)_kernel_malloc(sizeof(uint64_t), wait | M_ZERO); 32} 33 34 35static inline void 36counter_u64_free(counter_u64_t c) 37{ 38 _kernel_free(c); 39} 40 41 42static inline void 43counter_u64_add(counter_u64_t c, int64_t v) 44{ 45 atomic_add64((int64*)c, v); 46} 47 48 49static inline uint64_t 50counter_u64_fetch(counter_u64_t c) 51{ 52 return atomic_get64((int64*)c); 53} 54 55 56static inline void 57counter_u64_zero(counter_u64_t c) 58{ 59 atomic_set64((int64*)c, 0); 60} 61 62 63static inline void 64counter_enter() 65{ 66 // unneeded; counters are atomic 67} 68 69 70static inline void 71counter_exit() 72{ 73 // unneeded; counters are atomic 74} 75 76 77static inline void 78counter_u64_add_protected(counter_u64_t c, int64_t v) 79{ 80 // counters are atomic 81 counter_u64_add(c, v); 82} 83 84 85#endif 86