Per-cpu refcounters
Signed-off-by: Adam Rutkowski <adam.j.rutkowski@intel.com> Signed-off-by: Jan Musial <jan.musial@huawei.com> Signed-off-by: Michal Mielewczyk <michal.mielewczyk@huawei.com> Signed-off-by: Rafal Stefanowski <rafal.stefanowski@huawei.com>
This commit is contained in:

committed by
Michal Mielewczyk

parent
c200c24344
commit
53ee7c1d3a
81
env/posix/ocf_env_refcnt.c
vendored
Normal file
81
env/posix/ocf_env_refcnt.c
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Intel Corporation
|
||||
* Copyright(c) 2024 Huawei Technologies
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "ocf_env_refcnt.h"
|
||||
|
||||
int env_refcnt_init(struct env_refcnt *rc, const char *name, size_t name_len)
|
||||
{
|
||||
env_atomic_set(&rc->counter, 0);
|
||||
env_atomic_set(&rc->freeze, 0);
|
||||
env_atomic_set(&rc->callback, 0);
|
||||
rc->cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void env_refcnt_deinit(struct env_refcnt *rc)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void env_refcnt_dec(struct env_refcnt *rc)
|
||||
{
|
||||
int val = env_atomic_dec_return(&rc->counter);
|
||||
ENV_BUG_ON(val < 0);
|
||||
|
||||
if (!val && env_atomic_cmpxchg(&rc->callback, 1, 0))
|
||||
rc->cb(rc->priv);
|
||||
}
|
||||
|
||||
bool env_refcnt_inc(struct env_refcnt *rc)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (!env_atomic_read(&rc->freeze)) {
|
||||
val = env_atomic_inc_return(&rc->counter);
|
||||
if (!env_atomic_read(&rc->freeze))
|
||||
return !!val;
|
||||
else
|
||||
env_refcnt_dec(rc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void env_refcnt_freeze(struct env_refcnt *rc)
|
||||
{
|
||||
env_atomic_inc(&rc->freeze);
|
||||
}
|
||||
|
||||
void env_refcnt_register_zero_cb(struct env_refcnt *rc, env_refcnt_cb_t cb,
|
||||
void *priv)
|
||||
{
|
||||
ENV_BUG_ON(!env_atomic_read(&rc->freeze));
|
||||
ENV_BUG_ON(env_atomic_read(&rc->callback));
|
||||
|
||||
env_atomic_inc(&rc->counter);
|
||||
rc->cb = cb;
|
||||
rc->priv = priv;
|
||||
env_atomic_set(&rc->callback, 1);
|
||||
env_refcnt_dec(rc);
|
||||
}
|
||||
|
||||
void env_refcnt_unfreeze(struct env_refcnt *rc)
|
||||
{
|
||||
int val = env_atomic_dec_return(&rc->freeze);
|
||||
ENV_BUG_ON(val < 0);
|
||||
}
|
||||
|
||||
bool env_refcnt_frozen(struct env_refcnt *rc)
|
||||
{
|
||||
return !!env_atomic_read(&rc->freeze);
|
||||
}
|
||||
|
||||
bool env_refcnt_zeroed(struct env_refcnt *rc)
|
||||
{
|
||||
return (env_atomic_read(&rc->counter) == 0);
|
||||
}
|
54
env/posix/ocf_env_refcnt.h
vendored
Normal file
54
env/posix/ocf_env_refcnt.h
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Intel Corporation
|
||||
* Copyright(c) 2024-2025 Huawei Technologies
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __OCF_ENV_REFCNT_H__
|
||||
#define __OCF_ENV_REFCNT_H__
|
||||
|
||||
#include "ocf_env.h"
|
||||
|
||||
typedef void (*env_refcnt_cb_t)(void *priv);
|
||||
|
||||
struct env_refcnt
|
||||
{
|
||||
env_atomic counter __attribute__((aligned(64)));
|
||||
env_atomic freeze;
|
||||
env_atomic callback;
|
||||
env_refcnt_cb_t cb;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
/* Initialize reference counter */
|
||||
int env_refcnt_init(struct env_refcnt *rc, const char *name, size_t name_len);
|
||||
|
||||
void env_refcnt_deinit(struct env_refcnt *rc);
|
||||
|
||||
/* Try to increment counter. Returns true if successfull, false
|
||||
* if counter is frozen */
|
||||
bool env_refcnt_inc(struct env_refcnt *rc);
|
||||
|
||||
/* Decrement reference counter */
|
||||
void env_refcnt_dec(struct env_refcnt *rc);
|
||||
|
||||
/* Disallow incrementing of underlying counter - attempts to increment counter
|
||||
* will be failing until env_refcnt_unfreeze is calleed.
|
||||
* It's ok to call freeze multiple times, in which case counter is frozen
|
||||
* until all freeze calls are offset by a corresponding unfreeze.*/
|
||||
void env_refcnt_freeze(struct env_refcnt *rc);
|
||||
|
||||
/* Cancel the effect of single env_refcnt_freeze call */
|
||||
void env_refcnt_unfreeze(struct env_refcnt *rc);
|
||||
|
||||
bool env_refcnt_frozen(struct env_refcnt *rc);
|
||||
|
||||
bool env_refcnt_zeroed(struct env_refcnt *rc);
|
||||
|
||||
/* Register callback to be called when reference counter drops to 0.
|
||||
* Must be called after counter is frozen.
|
||||
* Cannot be called until previously regsitered callback had fired. */
|
||||
void env_refcnt_register_zero_cb(struct env_refcnt *rc, env_refcnt_cb_t cb,
|
||||
void *priv);
|
||||
|
||||
#endif // __OCF_ENV_REFCNT_H__
|
Reference in New Issue
Block a user