4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #ifndef __LIBOCF_ENV_H__
36 #define __LIBOCF_ENV_H__
45 #include <linux/limits.h>
46 #include <linux/stddef.h>
48 #include "spdk/stdinc.h"
49 #include "spdk/likely.h"
51 #include "spdk/util.h"
52 #include "spdk_internal/log.h"
54 #include "ocf_env_list.h"
55 #include "ocf/ocf_err.h"
62 typedef uint64_t sector_t
;
64 #define __packed __attribute__((packed))
65 #define __aligned(x) __attribute__((aligned(x)))
67 /* linux sector 512-bytes */
68 #define ENV_SECTOR_SHIFT 9
69 #define ENV_SECTOR_SIZE (1<<ENV_SECTOR_SHIFT)
70 #define BYTES_TO_SECTOR(x) ((x) >> ENV_SECTOR_SHIFT)
72 /* *** MEMORY MANAGEMENT *** */
74 #define ENV_MEM_NORMAL 0
75 #define ENV_MEM_NOIO 0
76 #define ENV_MEM_ATOMIC 0
78 #define likely spdk_likely
79 #define unlikely spdk_unlikely
81 #define min(x, y) MIN(x, y)
83 #define MIN(x, y) spdk_min(x, y)
86 #define ARRAY_SIZE(x) SPDK_COUNTOF(x)
89 #define ENV_PRIu64 PRIu64
91 #define ENV_WARN(cond, fmt, args...) ({ \
92 if (spdk_unlikely((uintptr_t)(cond))) \
93 SPDK_NOTICELOG("WARNING" fmt, ##args); \
96 #define ENV_WARN_ON(cond) ({ \
97 if (spdk_unlikely((uintptr_t)(cond))) \
98 SPDK_NOTICELOG("WARNING\n"); \
101 #define ENV_BUG() ({ \
102 SPDK_ERRLOG("BUG\n"); \
107 #define ENV_BUG_ON(cond) ({ \
108 if (spdk_unlikely((uintptr_t)(cond))) { \
109 SPDK_ERRLOG("BUG\n"); \
115 #define container_of(ptr, type, member) SPDK_CONTAINEROF(ptr, type, member)
117 static inline void *env_malloc(size_t size
, int flags
)
119 return spdk_malloc(size
, 0, NULL
, SPDK_ENV_LCORE_ID_ANY
,
123 static inline void *env_zalloc(size_t size
, int flags
)
125 return spdk_zmalloc(size
, 0, NULL
, SPDK_ENV_LCORE_ID_ANY
,
129 static inline void env_free(const void *ptr
)
131 return spdk_free((void *)ptr
);
134 static inline void *env_vmalloc(size_t size
)
136 return spdk_malloc(size
, 0, NULL
, SPDK_ENV_LCORE_ID_ANY
,
140 static inline void *env_vzalloc(size_t size
)
142 /* TODO: raw_ram init can request huge amount of memory to store
143 * hashtable in it. need to ensure that allocation succedds */
144 return spdk_zmalloc(size
, 0, NULL
, SPDK_ENV_LCORE_ID_ANY
,
148 static inline void *env_secure_alloc(size_t size
)
150 return spdk_zmalloc(size
, 0, NULL
, SPDK_ENV_LCORE_ID_ANY
,
154 static inline void env_secure_free(const void *ptr
, size_t size
)
156 return spdk_free((void *)ptr
);
159 static inline void env_vfree(const void *ptr
)
161 return spdk_free((void *)ptr
);
164 static inline uint64_t env_get_free_memory(void)
166 /* TODO: do we need implementation for this function? */
167 return sysconf(_SC_PAGESIZE
) * sysconf(_SC_AVPHYS_PAGES
);
170 /* *** ALLOCATOR *** */
172 #define OCF_ALLOCATOR_NAME_MAX 128
175 struct spdk_mempool
*mempool
;
179 env_allocator
*env_allocator_create(uint32_t size
, const char *name
);
181 void env_allocator_destroy(env_allocator
*allocator
);
183 void *env_allocator_new(env_allocator
*allocator
);
185 void env_allocator_del(env_allocator
*allocator
, void *item
);
187 uint32_t env_allocator_item_count(env_allocator
*allocator
);
195 static inline int env_mutex_init(env_mutex
*mutex
)
197 return !!pthread_mutex_init(&mutex
->m
, NULL
);
200 static inline void env_mutex_lock(env_mutex
*mutex
)
202 ENV_BUG_ON(pthread_mutex_lock(&mutex
->m
));
205 static inline int env_mutex_lock_interruptible(env_mutex
*mutex
)
207 env_mutex_lock(mutex
);
211 static inline int env_mutex_trylock(env_mutex
*mutex
)
213 return pthread_mutex_trylock(&mutex
->m
) ? -OCF_ERR_NO_LOCK
: 0;
216 static inline void env_mutex_unlock(env_mutex
*mutex
)
218 ENV_BUG_ON(pthread_mutex_unlock(&mutex
->m
));
221 static inline int env_mutex_is_locked(env_mutex
*mutex
)
223 if (env_mutex_trylock(mutex
) == 0) {
224 env_mutex_unlock(mutex
);
231 /* *** RECURSIVE MUTEX *** */
233 typedef env_mutex env_rmutex
;
235 static inline int env_rmutex_init(env_rmutex
*rmutex
)
237 return env_mutex_init(rmutex
);
240 static inline void env_rmutex_lock(env_rmutex
*rmutex
)
242 env_mutex_lock(rmutex
);
245 static inline int env_rmutex_lock_interruptible(env_rmutex
*rmutex
)
247 return env_mutex_lock_interruptible(rmutex
);
250 static inline int env_rmutex_trylock(env_rmutex
*rmutex
)
252 return env_mutex_trylock(rmutex
);
255 static inline void env_rmutex_unlock(env_rmutex
*rmutex
)
257 env_mutex_unlock(rmutex
);
260 static inline int env_rmutex_is_locked(env_rmutex
*rmutex
)
262 return env_mutex_is_locked(rmutex
);
265 /* *** RW SEMAPHORE *** */
267 pthread_rwlock_t lock
;
270 static inline int env_rwsem_init(env_rwsem
*s
)
272 return !!pthread_rwlock_init(&s
->lock
, NULL
);
275 static inline void env_rwsem_up_read(env_rwsem
*s
)
277 ENV_BUG_ON(pthread_rwlock_unlock(&s
->lock
));
280 static inline void env_rwsem_down_read(env_rwsem
*s
)
282 ENV_BUG_ON(pthread_rwlock_rdlock(&s
->lock
));
285 static inline int env_rwsem_down_read_trylock(env_rwsem
*s
)
287 return pthread_rwlock_tryrdlock(&s
->lock
) ? -OCF_ERR_NO_LOCK
: 0;
290 static inline void env_rwsem_up_write(env_rwsem
*s
)
292 ENV_BUG_ON(pthread_rwlock_unlock(&s
->lock
));
295 static inline void env_rwsem_down_write(env_rwsem
*s
)
297 ENV_BUG_ON(pthread_rwlock_wrlock(&s
->lock
));
300 static inline int env_rwsem_down_write_trylock(env_rwsem
*s
)
302 return pthread_rwlock_trywrlock(&s
->lock
) ? -OCF_ERR_NO_LOCK
: 0;
305 static inline int env_rwsem_is_locked(env_rwsem
*s
)
307 if (env_rwsem_down_read_trylock(s
) == 0) {
308 env_rwsem_up_read(s
);
315 static inline int env_rwsem_down_read_interruptible(env_rwsem
*s
)
317 return pthread_rwlock_rdlock(&s
->lock
);
319 static inline int env_rwsem_down_write_interruptible(env_rwsem
*s
)
321 return pthread_rwlock_wrlock(&s
->lock
);
324 /* *** ATOMIC VARIABLES *** */
326 typedef int env_atomic
;
328 typedef long env_atomic64
;
331 #define atomic_read(ptr) (*(__typeof__(*ptr) *volatile) (ptr))
335 #define atomic_set(ptr, i) ((*(__typeof__(*ptr) *volatile) (ptr)) = (i))
338 #define atomic_inc(ptr) ((void) __sync_fetch_and_add(ptr, 1))
339 #define atomic_dec(ptr) ((void) __sync_fetch_and_add(ptr, -1))
340 #define atomic_add(ptr, n) ((void) __sync_fetch_and_add(ptr, n))
341 #define atomic_sub(ptr, n) ((void) __sync_fetch_and_sub(ptr, n))
343 #define atomic_cmpxchg __sync_val_compare_and_swap
345 static inline int env_atomic_read(const env_atomic
*a
)
347 return atomic_read(a
);
350 static inline void env_atomic_set(env_atomic
*a
, int i
)
355 static inline void env_atomic_add(int i
, env_atomic
*a
)
360 static inline void env_atomic_sub(int i
, env_atomic
*a
)
365 static inline bool env_atomic_sub_and_test(int i
, env_atomic
*a
)
367 return __sync_sub_and_fetch(a
, i
) == 0;
370 static inline void env_atomic_inc(env_atomic
*a
)
375 static inline void env_atomic_dec(env_atomic
*a
)
380 static inline bool env_atomic_dec_and_test(env_atomic
*a
)
382 return __sync_sub_and_fetch(a
, 1) == 0;
385 static inline bool env_atomic_inc_and_test(env_atomic
*a
)
387 return __sync_add_and_fetch(a
, 1) == 0;
390 static inline int env_atomic_add_return(int i
, env_atomic
*a
)
392 return __sync_add_and_fetch(a
, i
);
395 static inline int env_atomic_sub_return(int i
, env_atomic
*a
)
397 return __sync_sub_and_fetch(a
, i
);
400 static inline int env_atomic_inc_return(env_atomic
*a
)
402 return env_atomic_add_return(1, a
);
405 static inline int env_atomic_dec_return(env_atomic
*a
)
407 return env_atomic_sub_return(1, a
);
410 static inline int env_atomic_cmpxchg(env_atomic
*a
, int old
, int new_value
)
412 return atomic_cmpxchg(a
, old
, new_value
);
415 static inline int env_atomic_add_unless(env_atomic
*a
, int i
, int u
)
418 c
= env_atomic_read(a
);
420 if (spdk_unlikely(c
== (u
))) {
423 old
= env_atomic_cmpxchg((a
), c
, c
+ (i
));
424 if (spdk_likely(old
== c
)) {
432 static inline long env_atomic64_read(const env_atomic64
*a
)
434 return atomic_read(a
);
437 static inline void env_atomic64_set(env_atomic64
*a
, long i
)
442 static inline void env_atomic64_add(long i
, env_atomic64
*a
)
447 static inline void env_atomic64_sub(long i
, env_atomic64
*a
)
452 static inline void env_atomic64_inc(env_atomic64
*a
)
457 static inline void env_atomic64_dec(env_atomic64
*a
)
462 static inline int env_atomic64_add_return(int i
, env_atomic
*a
)
464 return __sync_add_and_fetch(a
, i
);
467 static inline int env_atomic64_sub_return(int i
, env_atomic
*a
)
469 return __sync_sub_and_fetch(a
, i
);
472 static inline int env_atomic64_inc_return(env_atomic
*a
)
474 return env_atomic64_add_return(1, a
);
477 static inline int env_atomic64_dec_return(env_atomic
*a
)
479 return env_atomic_sub_return(1, a
);
482 static inline long env_atomic64_cmpxchg(env_atomic64
*a
, long old
, long new)
484 return atomic_cmpxchg(a
, old
, new);
487 /* *** COMPLETION *** */
492 typedef struct completion env_completion
;
494 void env_completion_init(env_completion
*completion
);
495 void env_completion_wait(env_completion
*completion
);
496 void env_completion_complete(env_completion
*completion
);
498 /* *** SPIN LOCKS *** */
500 typedef env_mutex env_spinlock
;
502 static inline void env_spinlock_init(env_spinlock
*l
)
507 static inline void env_spinlock_lock(env_spinlock
*l
)
512 static inline void env_spinlock_unlock(env_spinlock
*l
)
517 static inline void env_spinlock_lock_irq(env_spinlock
*l
)
519 env_spinlock_lock(l
);
522 static inline void env_spinlock_unlock_irq(env_spinlock
*l
)
524 env_spinlock_unlock(l
);
527 static inline void env_spinlock_lock_irqsave(env_spinlock
*l
, int flags
)
529 env_spinlock_lock(l
);
533 static inline void env_spinlock_unlock_irqrestore(env_spinlock
*l
, int flags
)
535 env_spinlock_unlock(l
);
539 /* *** RW LOCKS *** */
541 typedef env_rwsem env_rwlock
;
543 static inline void env_rwlock_init(env_rwlock
*l
)
548 static inline void env_rwlock_read_lock(env_rwlock
*l
)
550 env_rwsem_down_read(l
);
553 static inline void env_rwlock_read_unlock(env_rwlock
*l
)
555 env_rwsem_up_read(l
);
558 static inline void env_rwlock_write_lock(env_rwlock
*l
)
560 env_rwsem_down_write(l
);
563 static inline void env_rwlock_write_unlock(env_rwlock
*l
)
565 env_rwsem_up_write(l
);
568 static inline void env_bit_set(int nr
, volatile void *addr
)
570 char *byte
= (char *)addr
+ (nr
>> 3);
571 char mask
= 1 << (nr
& 7);
573 __sync_or_and_fetch(byte
, mask
);
576 static inline void env_bit_clear(int nr
, volatile void *addr
)
578 char *byte
= (char *)addr
+ (nr
>> 3);
579 char mask
= 1 << (nr
& 7);
582 __sync_and_and_fetch(byte
, mask
);
585 static inline bool env_bit_test(int nr
, const volatile unsigned long *addr
)
587 const char *byte
= (char *)addr
+ (nr
>> 3);
588 char mask
= 1 << (nr
& 7);
590 return !!(*byte
& mask
);
593 /* *** WAITQUEUE *** */
599 static inline void env_waitqueue_init(env_waitqueue
*w
)
601 sem_init(&w
->sem
, 0, 0);
604 static inline void env_waitqueue_wake_up(env_waitqueue
*w
)
609 #define env_waitqueue_wait(w, condition) \
617 /* *** SCHEDULING *** */
619 /* CAS does not need this while in user-space */
620 static inline void env_schedule(void)
624 #define env_cond_resched env_schedule
626 static inline int env_in_interrupt(void)
631 static inline uint64_t env_get_tick_count(void)
633 return spdk_get_ticks();
636 static inline uint64_t env_ticks_to_secs(uint64_t j
)
638 return j
/ spdk_get_ticks_hz();
641 static inline uint64_t env_ticks_to_msecs(uint64_t j
)
643 return env_ticks_to_secs(j
) * 1000;
646 static inline uint64_t env_ticks_to_nsecs(uint64_t j
)
648 return env_ticks_to_secs(j
) * 1000 * 1000;
651 static inline uint64_t env_ticks_to_usecs(uint64_t j
)
653 return env_ticks_to_secs(j
) * 1000 * 1000 * 1000;
656 static inline uint64_t env_secs_to_ticks(uint64_t j
)
658 return j
* spdk_get_ticks_hz();
661 /* *** STRING OPERATIONS *** */
663 /* 256 KB is sufficient amount of memory for OCF operations */
664 #define ENV_MAX_MEM (256 * 1024)
666 static inline int env_memset(void *dest
, size_t len
, uint8_t value
)
668 if (dest
== NULL
|| len
== 0) {
672 memset(dest
, value
, len
);
676 static inline int env_memcpy(void *dest
, size_t dmax
, const void *src
, size_t len
)
678 if (dest
== NULL
|| src
== NULL
) {
681 if (dmax
== 0 || dmax
> ENV_MAX_MEM
) {
684 if (len
== 0 || len
> dmax
) {
688 memcpy(dest
, src
, len
);
692 static inline int env_memcmp(const void *aptr
, size_t dmax
, const void *bptr
, size_t len
,
695 if (diff
== NULL
|| aptr
== NULL
|| bptr
== NULL
) {
698 if (dmax
== 0 || dmax
> ENV_MAX_MEM
) {
701 if (len
== 0 || len
> dmax
) {
705 *diff
= memcmp(aptr
, bptr
, len
);
709 /* 4096 is sufficient max length for any OCF operation on string */
710 #define ENV_MAX_STR (4 * 1024)
712 static inline size_t env_strnlen(const char *src
, size_t dmax
)
714 return strnlen(src
, dmax
);
717 static inline int env_strncpy(char *dest
, size_t dmax
, const char *src
, size_t len
)
719 if (dest
== NULL
|| src
== NULL
) {
722 if (dmax
== 0 || dmax
> ENV_MAX_STR
) {
725 if (len
== 0 || len
> dmax
) {
729 strncpy(dest
, src
, len
);
733 #define env_strncmp strncmp
735 static inline char *env_strdup(const char *src
, int flags
)
744 len
= env_strnlen(src
, ENV_MAX_STR
) + 1;
745 ret
= env_malloc(len
, flags
);
747 if (env_strncpy(ret
, ENV_MAX_STR
, src
, len
)) {
754 /* *** SORTING *** */
756 static inline void env_sort(void *base
, size_t num
, size_t size
,
757 int (*cmp_fn
)(const void *, const void *),
758 void (*swap_fn
)(void *, void *, int size
))
760 qsort(base
, num
, size
, cmp_fn
);
763 static inline void env_msleep(uint64_t n
)
768 static inline void env_touch_softlockup_wd(void)
774 uint32_t env_crc32(uint32_t crc
, uint8_t const *data
, size_t len
);
776 #endif /* __OCF_ENV_H__ */