Finish separating cacheline conc and alock
Signed-off-by: Adam Rutkowski <adam.j.rutkowski@intel.com>
This commit is contained in:
parent
d22a3ad0e0
commit
2cb7270f63
@ -54,8 +54,7 @@ struct ocf_alock {
|
|||||||
env_mutex lock;
|
env_mutex lock;
|
||||||
env_atomic *access;
|
env_atomic *access;
|
||||||
env_atomic waiting;
|
env_atomic waiting;
|
||||||
size_t access_limit;
|
ocf_cache_line_t num_entries;
|
||||||
ocf_cache_line_t num_clines;
|
|
||||||
env_allocator *allocator;
|
env_allocator *allocator;
|
||||||
struct ocf_alock_waiters_list waiters_lsts[_WAITERS_LIST_ENTRIES];
|
struct ocf_alock_waiters_list waiters_lsts[_WAITERS_LIST_ENTRIES];
|
||||||
|
|
||||||
@ -82,48 +81,6 @@ struct ocf_alock_lock_cbs
|
|||||||
ocf_cl_lock_line_mark_locked_cb line_mark_locked;
|
ocf_cl_lock_line_mark_locked_cb line_mark_locked;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool ocf_cl_lock_line_needs_lock(struct ocf_request *req,
|
|
||||||
unsigned index)
|
|
||||||
{
|
|
||||||
/* Remapped cachelines are assigned cacheline lock individually
|
|
||||||
* during eviction
|
|
||||||
*/
|
|
||||||
return req->map[index].status != LOOKUP_MISS &&
|
|
||||||
req->map[index].status != LOOKUP_REMAPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ocf_cl_lock_line_is_acting(struct ocf_request *req,
|
|
||||||
unsigned index)
|
|
||||||
{
|
|
||||||
return req->map[index].status != LOOKUP_MISS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ocf_cl_lock_line_is_locked(struct ocf_request *req,
|
|
||||||
unsigned index, int rw)
|
|
||||||
{
|
|
||||||
if (rw == OCF_WRITE)
|
|
||||||
return req->map[index].wr_locked;
|
|
||||||
else
|
|
||||||
return req->map[index].rd_locked;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ocf_cl_lock_line_mark_locked(struct ocf_request *req,
|
|
||||||
unsigned index, int rw, bool locked)
|
|
||||||
{
|
|
||||||
if (rw == OCF_WRITE)
|
|
||||||
req->map[index].wr_locked = locked;
|
|
||||||
else
|
|
||||||
req->map[index].rd_locked = locked;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ocf_alock_lock_cbs ocf_cline_conc_cbs = {
|
|
||||||
.line_needs_lock = ocf_cl_lock_line_needs_lock,
|
|
||||||
.line_is_acting = ocf_cl_lock_line_is_acting,
|
|
||||||
.line_is_locked = ocf_cl_lock_line_is_locked,
|
|
||||||
.line_mark_locked = ocf_cl_lock_line_mark_locked
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -131,13 +88,12 @@ static struct ocf_alock_lock_cbs ocf_cline_conc_cbs = {
|
|||||||
#define ALLOCATOR_NAME_FMT "ocf_%s_concurrency"
|
#define ALLOCATOR_NAME_FMT "ocf_%s_concurrency"
|
||||||
#define ALLOCATOR_NAME_MAX (sizeof(ALLOCATOR_NAME_FMT) + OCF_CACHE_NAME_SIZE)
|
#define ALLOCATOR_NAME_MAX (sizeof(ALLOCATOR_NAME_FMT) + OCF_CACHE_NAME_SIZE)
|
||||||
|
|
||||||
int ocf_cache_line_concurrency_init(struct ocf_alock **self,
|
int ocf_alock_init(struct ocf_alock **self, unsigned num_entries,
|
||||||
unsigned num_clines, ocf_cache_t cache)
|
const char* name, ocf_cache_t cache)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
struct ocf_alock *alock;
|
struct ocf_alock *alock;
|
||||||
char name[ALLOCATOR_NAME_MAX];
|
|
||||||
|
|
||||||
OCF_DEBUG_TRACE(cache);
|
OCF_DEBUG_TRACE(cache);
|
||||||
|
|
||||||
@ -148,7 +104,7 @@ int ocf_cache_line_concurrency_init(struct ocf_alock **self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
alock->cache = cache;
|
alock->cache = cache;
|
||||||
alock->num_clines = num_clines;
|
alock->num_entries = num_entries;
|
||||||
|
|
||||||
error = env_mutex_init(&alock->lock);
|
error = env_mutex_init(&alock->lock);
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -156,19 +112,13 @@ int ocf_cache_line_concurrency_init(struct ocf_alock **self,
|
|||||||
goto rwsem_err;
|
goto rwsem_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
alock->access = env_vzalloc(num_clines * sizeof(alock->access[0]));
|
alock->access = env_vzalloc(num_entries * sizeof(alock->access[0]));
|
||||||
|
|
||||||
if (!alock->access) {
|
if (!alock->access) {
|
||||||
error = __LINE__;
|
error = __LINE__;
|
||||||
goto allocation_err;
|
goto allocation_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snprintf(name, sizeof(name), ALLOCATOR_NAME_FMT,
|
|
||||||
ocf_cache_get_name(cache)) < 0) {
|
|
||||||
error = __LINE__;
|
|
||||||
goto allocation_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
alock->allocator = env_allocator_create(sizeof(struct ocf_alock_waiter), name, false);
|
alock->allocator = env_allocator_create(sizeof(struct ocf_alock_waiter), name, false);
|
||||||
if (!alock->allocator) {
|
if (!alock->allocator) {
|
||||||
error = __LINE__;
|
error = __LINE__;
|
||||||
@ -215,7 +165,7 @@ exit_err:
|
|||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void ocf_cache_line_concurrency_deinit(struct ocf_alock **self)
|
void ocf_alock_deinit(struct ocf_alock **self)
|
||||||
{
|
{
|
||||||
struct ocf_alock *concurrency = *self;
|
struct ocf_alock *concurrency = *self;
|
||||||
int i;
|
int i;
|
||||||
@ -231,8 +181,7 @@ void ocf_cache_line_concurrency_deinit(struct ocf_alock **self)
|
|||||||
env_spinlock_destroy(&concurrency->waiters_lsts[i].lock);
|
env_spinlock_destroy(&concurrency->waiters_lsts[i].lock);
|
||||||
|
|
||||||
if (concurrency->access)
|
if (concurrency->access)
|
||||||
OCF_REALLOC_DEINIT(&concurrency->access,
|
env_vfree(concurrency->access);
|
||||||
&concurrency->access_limit);
|
|
||||||
|
|
||||||
if (concurrency->allocator)
|
if (concurrency->allocator)
|
||||||
env_allocator_destroy(concurrency->allocator);
|
env_allocator_destroy(concurrency->allocator);
|
||||||
@ -242,12 +191,12 @@ void ocf_cache_line_concurrency_deinit(struct ocf_alock **self)
|
|||||||
*self = NULL;
|
*self = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ocf_cache_line_concurrency_size_of(ocf_cache_t cache)
|
size_t ocf_alock_size(unsigned num_entries)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
size = sizeof(env_atomic);
|
size = sizeof(env_atomic);
|
||||||
size *= cache->device->collision_table_entries;
|
size *= num_entries;
|
||||||
|
|
||||||
size += sizeof(struct ocf_alock);
|
size += sizeof(struct ocf_alock);
|
||||||
|
|
||||||
@ -257,7 +206,7 @@ size_t ocf_cache_line_concurrency_size_of(ocf_cache_t cache)
|
|||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static inline bool ocf_alock_waitlist_are_waiters(struct ocf_alock *alock,
|
static inline bool ocf_alock_waitlist_is_empty_locked(struct ocf_alock *alock,
|
||||||
ocf_cache_line_t line)
|
ocf_cache_line_t line)
|
||||||
{
|
{
|
||||||
bool are = false;
|
bool are = false;
|
||||||
@ -268,7 +217,7 @@ static inline bool ocf_alock_waitlist_are_waiters(struct ocf_alock *alock,
|
|||||||
|
|
||||||
/* If list empty that means there are no waiters on cache line */
|
/* If list empty that means there are no waiters on cache line */
|
||||||
if (list_empty(&lst->head))
|
if (list_empty(&lst->head))
|
||||||
return false;
|
return true;
|
||||||
|
|
||||||
list_for_each(iter, &lst->head) {
|
list_for_each(iter, &lst->head) {
|
||||||
waiter = list_entry(iter, struct ocf_alock_waiter, item);
|
waiter = list_entry(iter, struct ocf_alock_waiter, item);
|
||||||
@ -279,7 +228,7 @@ static inline bool ocf_alock_waitlist_are_waiters(struct ocf_alock *alock,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return are;
|
return !are;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -297,15 +246,15 @@ static inline void ocf_alock_waitlist_add(struct ocf_alock *alock,
|
|||||||
|
|
||||||
#define ocf_alock_waitlist_lock(cncrrncy, line, flags) \
|
#define ocf_alock_waitlist_lock(cncrrncy, line, flags) \
|
||||||
do { \
|
do { \
|
||||||
uint32_t idx = _WAITERS_LIST_ITEM(line); \
|
uint32_t list = _WAITERS_LIST_ITEM(line); \
|
||||||
struct ocf_alock_waiters_list *lst = &cncrrncy->waiters_lsts[idx]; \
|
struct ocf_alock_waiters_list *lst = &cncrrncy->waiters_lsts[list]; \
|
||||||
env_spinlock_lock_irqsave(&lst->lock, flags); \
|
env_spinlock_lock_irqsave(&lst->lock, flags); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ocf_alock_waitlist_unlock(cncrrncy, line, flags) \
|
#define ocf_alock_waitlist_unlock(cncrrncy, line, flags) \
|
||||||
do { \
|
do { \
|
||||||
uint32_t idx = _WAITERS_LIST_ITEM(line); \
|
uint32_t list = _WAITERS_LIST_ITEM(line); \
|
||||||
struct ocf_alock_waiters_list *lst = &cncrrncy->waiters_lsts[idx]; \
|
struct ocf_alock_waiters_list *lst = &cncrrncy->waiters_lsts[list]; \
|
||||||
env_spinlock_unlock_irqrestore(&lst->lock, flags); \
|
env_spinlock_unlock_irqrestore(&lst->lock, flags); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -439,7 +388,7 @@ static inline bool ocf_alock_trylock_entry_rd2rd(struct ocf_alock *alock,
|
|||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void ocf_alock_on_lock(struct ocf_alock *alock,
|
static void ocf_alock_entry_locked(struct ocf_alock *alock,
|
||||||
struct ocf_request *req, ocf_req_async_lock_cb cmpl)
|
struct ocf_request *req, ocf_req_async_lock_cb cmpl)
|
||||||
{
|
{
|
||||||
if (env_atomic_dec_return(&req->lock_remaining) == 0) {
|
if (env_atomic_dec_return(&req->lock_remaining) == 0) {
|
||||||
@ -468,7 +417,7 @@ static inline bool ocf_alock_lock_one_wr(struct ocf_alock *alock,
|
|||||||
if (ocf_alock_trylock_entry_wr(alock, line)) {
|
if (ocf_alock_trylock_entry_wr(alock, line)) {
|
||||||
/* lock was not owned by anyone */
|
/* lock was not owned by anyone */
|
||||||
cbs->line_mark_locked(req, idx, OCF_WRITE, true);
|
cbs->line_mark_locked(req, idx, OCF_WRITE, true);
|
||||||
ocf_alock_on_lock(alock, req, cmpl);
|
ocf_alock_entry_locked(alock, req, cmpl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,7 +450,7 @@ unlock:
|
|||||||
|
|
||||||
if (!waiting) {
|
if (!waiting) {
|
||||||
cbs->line_mark_locked(req, idx, OCF_WRITE, true);
|
cbs->line_mark_locked(req, idx, OCF_WRITE, true);
|
||||||
ocf_alock_on_lock(alock, req, cmpl);
|
ocf_alock_entry_locked(alock, req, cmpl);
|
||||||
env_allocator_del(alock->allocator, waiter);
|
env_allocator_del(alock->allocator, waiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,7 +475,7 @@ static inline bool ocf_alock_lock_one_rd(struct ocf_alock *alock,
|
|||||||
if( ocf_alock_trylock_entry_rd_idle(alock, line)) {
|
if( ocf_alock_trylock_entry_rd_idle(alock, line)) {
|
||||||
/* lock was not owned by anyone */
|
/* lock was not owned by anyone */
|
||||||
cbs->line_mark_locked(req, idx, OCF_READ, true);
|
cbs->line_mark_locked(req, idx, OCF_READ, true);
|
||||||
ocf_alock_on_lock(alock, req, cmpl);
|
ocf_alock_entry_locked(alock, req, cmpl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,7 +486,7 @@ static inline bool ocf_alock_lock_one_rd(struct ocf_alock *alock,
|
|||||||
/* Lock waiters list */
|
/* Lock waiters list */
|
||||||
ocf_alock_waitlist_lock(alock, line, flags);
|
ocf_alock_waitlist_lock(alock, line, flags);
|
||||||
|
|
||||||
if (!ocf_alock_waitlist_are_waiters(alock, line)) {
|
if (!ocf_alock_waitlist_is_empty_locked(alock, line)) {
|
||||||
/* No waiters at the moment */
|
/* No waiters at the moment */
|
||||||
|
|
||||||
/* Check if read lock can be obtained */
|
/* Check if read lock can be obtained */
|
||||||
@ -564,7 +513,7 @@ unlock:
|
|||||||
|
|
||||||
if (!waiting) {
|
if (!waiting) {
|
||||||
cbs->line_mark_locked(req, idx, OCF_READ, true);
|
cbs->line_mark_locked(req, idx, OCF_READ, true);
|
||||||
ocf_alock_on_lock(alock, req, cmpl);
|
ocf_alock_entry_locked(alock, req, cmpl);
|
||||||
env_allocator_del(alock->allocator, waiter);
|
env_allocator_del(alock->allocator, waiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,7 +572,7 @@ static inline void ocf_alock_unlock_one_rd_common(struct ocf_alock *alock,
|
|||||||
|
|
||||||
cbs->line_mark_locked(waiter->req, waiter->idx,
|
cbs->line_mark_locked(waiter->req, waiter->idx,
|
||||||
waiter->rw, true);
|
waiter->rw, true);
|
||||||
ocf_alock_on_lock(alock, waiter->req, waiter->cmpl);
|
ocf_alock_entry_locked(alock, waiter->req, waiter->cmpl);
|
||||||
|
|
||||||
env_allocator_del(alock->allocator, waiter);
|
env_allocator_del(alock->allocator, waiter);
|
||||||
} else {
|
} else {
|
||||||
@ -639,6 +588,12 @@ static inline void ocf_alock_unlock_one_rd_common(struct ocf_alock *alock,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ocf_alock_trylock_one_rd(struct ocf_alock *alock,
|
||||||
|
ocf_cache_line_t line)
|
||||||
|
{
|
||||||
|
return ocf_alock_trylock_entry_rd_idle(alock, line);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -707,7 +662,7 @@ static inline void ocf_alock_unlock_one_wr_common(struct ocf_alock *alock,
|
|||||||
|
|
||||||
cbs->line_mark_locked(waiter->req, waiter->idx,
|
cbs->line_mark_locked(waiter->req, waiter->idx,
|
||||||
waiter->rw, true);
|
waiter->rw, true);
|
||||||
ocf_alock_on_lock(alock, waiter->req, waiter->cmpl);
|
ocf_alock_entry_locked(alock, waiter->req, waiter->cmpl);
|
||||||
|
|
||||||
env_allocator_del(alock->allocator, waiter);
|
env_allocator_del(alock->allocator, waiter);
|
||||||
} else {
|
} else {
|
||||||
@ -798,7 +753,7 @@ static int ocf_alock_lock_rd_fast(struct ocf_alock *alock,
|
|||||||
}
|
}
|
||||||
|
|
||||||
line = req->map[i].coll_idx;
|
line = req->map[i].coll_idx;
|
||||||
ENV_BUG_ON(line >= alock->num_clines);
|
ENV_BUG_ON(line >= alock->num_entries);
|
||||||
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_READ));
|
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_READ));
|
||||||
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_WRITE));
|
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_WRITE));
|
||||||
|
|
||||||
@ -860,7 +815,7 @@ static int ocf_alock_lock_rd_slow(struct ocf_alock *alock,
|
|||||||
}
|
}
|
||||||
|
|
||||||
line = req->map[i].coll_idx;
|
line = req->map[i].coll_idx;
|
||||||
ENV_BUG_ON(line >= alock->num_clines);
|
ENV_BUG_ON(line >= alock->num_entries);
|
||||||
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_READ));
|
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_READ));
|
||||||
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_WRITE));
|
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_WRITE));
|
||||||
|
|
||||||
@ -909,15 +864,6 @@ static int ocf_alock_lock_rd(struct ocf_alock *alock,
|
|||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocf_req_async_lock_rd(struct ocf_alock *alock,
|
|
||||||
struct ocf_request *req, ocf_req_async_lock_cb cmpl)
|
|
||||||
{
|
|
||||||
struct ocf_alock_lock_cbs *cbs =
|
|
||||||
&ocf_cline_conc_cbs;
|
|
||||||
|
|
||||||
return ocf_alock_lock_rd(alock, cbs, req, cmpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to write-lock request without adding waiters. Function should be called
|
/* Try to write-lock request without adding waiters. Function should be called
|
||||||
* under read lock, multiple threads may attempt to acquire the lock
|
* under read lock, multiple threads may attempt to acquire the lock
|
||||||
* concurrently. */
|
* concurrently. */
|
||||||
@ -938,7 +884,7 @@ static int ocf_alock_lock_wr_fast(struct ocf_alock *alock,
|
|||||||
}
|
}
|
||||||
|
|
||||||
line = req->map[i].coll_idx;
|
line = req->map[i].coll_idx;
|
||||||
ENV_BUG_ON(line >= alock->num_clines);
|
ENV_BUG_ON(line >= alock->num_entries);
|
||||||
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_READ));
|
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_READ));
|
||||||
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_WRITE));
|
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_WRITE));
|
||||||
|
|
||||||
@ -1000,7 +946,7 @@ static int ocf_alock_lock_wr_slow(struct ocf_alock *alock,
|
|||||||
}
|
}
|
||||||
|
|
||||||
line = req->map[i].coll_idx;
|
line = req->map[i].coll_idx;
|
||||||
ENV_BUG_ON(line >= alock->num_clines);
|
ENV_BUG_ON(line >= alock->num_entries);
|
||||||
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_READ));
|
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_READ));
|
||||||
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_WRITE));
|
ENV_BUG_ON(cbs->line_is_locked(req, i, OCF_WRITE));
|
||||||
|
|
||||||
@ -1048,15 +994,6 @@ int ocf_alock_lock_wr(struct ocf_alock *alock,
|
|||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocf_req_async_lock_wr(struct ocf_alock *alock,
|
|
||||||
struct ocf_request *req, ocf_req_async_lock_cb cmpl)
|
|
||||||
{
|
|
||||||
struct ocf_alock_lock_cbs *cbs =
|
|
||||||
&ocf_cline_conc_cbs;
|
|
||||||
|
|
||||||
return ocf_alock_lock_wr(alock, cbs, req, cmpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -1080,21 +1017,13 @@ void ocf_alock_unlock_rd(struct ocf_alock *alock,
|
|||||||
|
|
||||||
line = req->map[i].coll_idx;
|
line = req->map[i].coll_idx;
|
||||||
|
|
||||||
ENV_BUG_ON(line >= alock->num_clines);
|
ENV_BUG_ON(line >= alock->num_entries);
|
||||||
|
|
||||||
ocf_alock_unlock_one_rd(alock, cbs, line);
|
ocf_alock_unlock_one_rd(alock, cbs, line);
|
||||||
cbs->line_mark_locked(req, i, OCF_READ, false);
|
cbs->line_mark_locked(req, i, OCF_READ, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ocf_req_unlock_rd(struct ocf_alock *alock, struct ocf_request *req)
|
|
||||||
{
|
|
||||||
struct ocf_alock_lock_cbs *cbs =
|
|
||||||
&ocf_cline_conc_cbs;
|
|
||||||
|
|
||||||
ocf_alock_unlock_rd(alock, cbs, req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -1118,21 +1047,13 @@ void ocf_alock_unlock_wr(struct ocf_alock *alock,
|
|||||||
|
|
||||||
line = req->map[i].coll_idx;
|
line = req->map[i].coll_idx;
|
||||||
|
|
||||||
ENV_BUG_ON(line >= alock->num_clines);
|
ENV_BUG_ON(line >= alock->num_entries);
|
||||||
|
|
||||||
ocf_alock_unlock_one_wr(alock, cbs, line);
|
ocf_alock_unlock_one_wr(alock, cbs, line);
|
||||||
cbs->line_mark_locked(req, i, OCF_WRITE, false);
|
cbs->line_mark_locked(req, i, OCF_WRITE, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ocf_req_unlock_wr(struct ocf_alock *alock, struct ocf_request *req)
|
|
||||||
{
|
|
||||||
struct ocf_alock_lock_cbs *cbs =
|
|
||||||
&ocf_cline_conc_cbs;
|
|
||||||
|
|
||||||
ocf_alock_unlock_wr(alock, cbs, req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -1150,7 +1071,7 @@ void ocf_alock_unlock(struct ocf_alock *alock,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
line = req->map[i].coll_idx;
|
line = req->map[i].coll_idx;
|
||||||
ENV_BUG_ON(line >= alock->num_clines);
|
ENV_BUG_ON(line >= alock->num_entries);
|
||||||
|
|
||||||
if (cbs->line_is_locked(req, i, OCF_READ) &&
|
if (cbs->line_is_locked(req, i, OCF_READ) &&
|
||||||
cbs->line_is_locked(req, i, OCF_WRITE)) {
|
cbs->line_is_locked(req, i, OCF_WRITE)) {
|
||||||
@ -1165,14 +1086,6 @@ void ocf_alock_unlock(struct ocf_alock *alock,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ocf_req_unlock(struct ocf_alock *alock, struct ocf_request *req)
|
|
||||||
{
|
|
||||||
struct ocf_alock_lock_cbs *cbs =
|
|
||||||
&ocf_cline_conc_cbs;
|
|
||||||
|
|
||||||
ocf_alock_unlock(alock, cbs, req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -1196,22 +1109,13 @@ void ocf_alock_unlock_one(struct ocf_alock *alock,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ocf_req_unlock_entry(struct ocf_alock *alock,
|
|
||||||
struct ocf_request *req, uint32_t entry)
|
|
||||||
{
|
|
||||||
struct ocf_alock_lock_cbs *cbs =
|
|
||||||
&ocf_cline_conc_cbs;
|
|
||||||
|
|
||||||
ocf_alock_unlock_one(alock, cbs, req, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool ocf_cache_line_is_used(struct ocf_alock *alock,
|
bool ocf_cache_line_is_used(struct ocf_alock *alock,
|
||||||
ocf_cache_line_t line)
|
ocf_cache_line_t line)
|
||||||
{
|
{
|
||||||
ENV_BUG_ON(line >= alock->num_clines);
|
ENV_BUG_ON(line >= alock->num_entries);
|
||||||
|
|
||||||
if (env_atomic_read(&(alock->access[line])))
|
if (env_atomic_read(&(alock->access[line])))
|
||||||
return true;
|
return true;
|
||||||
@ -1225,37 +1129,34 @@ bool ocf_cache_line_is_used(struct ocf_alock *alock,
|
|||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool ocf_cache_line_are_waiters(struct ocf_alock *alock,
|
bool ocf_alock_waitlist_is_empty(struct ocf_alock *alock, unsigned line)
|
||||||
ocf_cache_line_t line)
|
|
||||||
{
|
{
|
||||||
bool are;
|
bool empty;
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
|
|
||||||
ENV_BUG_ON(line >= alock->num_clines);
|
ENV_BUG_ON(line >= alock->num_entries);
|
||||||
|
|
||||||
/* Lock waiters list */
|
/* Lock waiters list */
|
||||||
ocf_alock_waitlist_lock(alock, line, flags);
|
ocf_alock_waitlist_lock(alock, line, flags);
|
||||||
|
|
||||||
are = ocf_alock_waitlist_are_waiters(alock, line);
|
empty = ocf_alock_waitlist_is_empty_locked(alock, line);
|
||||||
|
|
||||||
ocf_alock_waitlist_unlock(alock, line, flags);
|
ocf_alock_waitlist_unlock(alock, line, flags);
|
||||||
|
|
||||||
return are;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: it is caller responsibility to assure that noone acquires
|
/* NOTE: it is caller responsibility to assure that noone acquires
|
||||||
* a lock in background */
|
* a lock in background */
|
||||||
bool ocf_cache_line_is_locked_exclusively(struct ocf_cache *cache,
|
bool ocf_alock_is_locked_exclusively(struct ocf_alock *alock,
|
||||||
ocf_cache_line_t line)
|
unsigned idx)
|
||||||
{
|
{
|
||||||
struct ocf_alock *alock =
|
env_atomic *access = &alock->access[idx];
|
||||||
ocf_cache_line_concurrency(cache);
|
|
||||||
env_atomic *access = &alock->access[line];
|
|
||||||
int val = env_atomic_read(access);
|
int val = env_atomic_read(access);
|
||||||
|
|
||||||
ENV_BUG_ON(val == OCF_CACHE_LINE_ACCESS_IDLE);
|
ENV_BUG_ON(val == OCF_CACHE_LINE_ACCESS_IDLE);
|
||||||
|
|
||||||
if (ocf_cache_line_are_waiters(alock, line))
|
if (!ocf_alock_waitlist_is_empty(alock, idx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return val == OCF_CACHE_LINE_ACCESS_ONE_RD ||
|
return val == OCF_CACHE_LINE_ACCESS_ONE_RD ||
|
||||||
@ -1265,20 +1166,59 @@ bool ocf_cache_line_is_locked_exclusively(struct ocf_cache *cache,
|
|||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
uint32_t ocf_cache_line_concurrency_suspended_no(struct ocf_alock *alock)
|
uint32_t ocf_alock_waitlist_count(struct ocf_alock *alock)
|
||||||
{
|
{
|
||||||
return env_atomic_read(&alock->waiting);
|
return env_atomic_read(&alock->waiting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ocf_cl_lock_line_needs_lock(struct ocf_request *req,
|
||||||
|
unsigned index)
|
||||||
|
{
|
||||||
|
/* Remapped cachelines are assigned cacheline lock individually
|
||||||
|
* during eviction
|
||||||
|
*/
|
||||||
|
return req->map[index].status != LOOKUP_MISS &&
|
||||||
|
req->map[index].status != LOOKUP_REMAPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ocf_cl_lock_line_is_acting(struct ocf_request *req,
|
||||||
|
unsigned index)
|
||||||
|
{
|
||||||
|
return req->map[index].status != LOOKUP_MISS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ocf_cl_lock_line_is_locked(struct ocf_request *req,
|
||||||
|
unsigned index, int rw)
|
||||||
|
{
|
||||||
|
if (rw == OCF_WRITE)
|
||||||
|
return req->map[index].wr_locked;
|
||||||
|
else
|
||||||
|
return req->map[index].rd_locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ocf_cl_lock_line_mark_locked(struct ocf_request *req,
|
||||||
|
unsigned index, int rw, bool locked)
|
||||||
|
{
|
||||||
|
if (rw == OCF_WRITE)
|
||||||
|
req->map[index].wr_locked = locked;
|
||||||
|
else
|
||||||
|
req->map[index].rd_locked = locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ocf_alock_lock_cbs ocf_cline_conc_cbs = {
|
||||||
|
.line_needs_lock = ocf_cl_lock_line_needs_lock,
|
||||||
|
.line_is_acting = ocf_cl_lock_line_is_acting,
|
||||||
|
.line_is_locked = ocf_cl_lock_line_is_locked,
|
||||||
|
.line_mark_locked = ocf_cl_lock_line_mark_locked
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
bool ocf_cache_line_try_lock_rd(struct ocf_alock *alock,
|
bool ocf_cache_line_try_lock_rd(struct ocf_alock *alock,
|
||||||
ocf_cache_line_t line)
|
ocf_cache_line_t line)
|
||||||
{
|
{
|
||||||
return ocf_alock_trylock_entry_rd_idle(alock, line);
|
return ocf_alock_trylock_one_rd(alock, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void ocf_cache_line_unlock_rd(struct ocf_alock *alock, ocf_cache_line_t line)
|
void ocf_cache_line_unlock_rd(struct ocf_alock *alock, ocf_cache_line_t line)
|
||||||
{
|
{
|
||||||
struct ocf_alock_lock_cbs *cbs =
|
struct ocf_alock_lock_cbs *cbs =
|
||||||
@ -1303,3 +1243,96 @@ void ocf_cache_line_unlock_wr(struct ocf_alock *alock,
|
|||||||
OCF_DEBUG_RQ(alock->cache, "Cache line = %u", line);
|
OCF_DEBUG_RQ(alock->cache, "Cache line = %u", line);
|
||||||
ocf_alock_unlock_one_wr(alock, cbs, line);
|
ocf_alock_unlock_one_wr(alock, cbs, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ocf_req_async_lock_rd(struct ocf_alock *alock,
|
||||||
|
struct ocf_request *req, ocf_req_async_lock_cb cmpl)
|
||||||
|
{
|
||||||
|
struct ocf_alock_lock_cbs *cbs =
|
||||||
|
&ocf_cline_conc_cbs;
|
||||||
|
|
||||||
|
return ocf_alock_lock_rd(alock, cbs, req, cmpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ocf_req_async_lock_wr(struct ocf_alock *alock,
|
||||||
|
struct ocf_request *req, ocf_req_async_lock_cb cmpl)
|
||||||
|
{
|
||||||
|
struct ocf_alock_lock_cbs *cbs =
|
||||||
|
&ocf_cline_conc_cbs;
|
||||||
|
|
||||||
|
return ocf_alock_lock_wr(alock, cbs, req, cmpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ocf_req_unlock_rd(struct ocf_alock *alock, struct ocf_request *req)
|
||||||
|
{
|
||||||
|
struct ocf_alock_lock_cbs *cbs =
|
||||||
|
&ocf_cline_conc_cbs;
|
||||||
|
|
||||||
|
ocf_alock_unlock_rd(alock, cbs, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ocf_req_unlock_wr(struct ocf_alock *alock, struct ocf_request *req)
|
||||||
|
{
|
||||||
|
struct ocf_alock_lock_cbs *cbs =
|
||||||
|
&ocf_cline_conc_cbs;
|
||||||
|
|
||||||
|
ocf_alock_unlock_wr(alock, cbs, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ocf_req_unlock(struct ocf_alock *alock, struct ocf_request *req)
|
||||||
|
{
|
||||||
|
struct ocf_alock_lock_cbs *cbs =
|
||||||
|
&ocf_cline_conc_cbs;
|
||||||
|
|
||||||
|
ocf_alock_unlock(alock, cbs, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ocf_cache_line_are_waiters(struct ocf_alock *alock,
|
||||||
|
ocf_cache_line_t line)
|
||||||
|
{
|
||||||
|
return !ocf_alock_waitlist_is_empty(alock, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ocf_cache_line_is_locked_exclusively(struct ocf_cache *cache,
|
||||||
|
ocf_cache_line_t line)
|
||||||
|
{
|
||||||
|
struct ocf_alock *alock =
|
||||||
|
ocf_cache_line_concurrency(cache);
|
||||||
|
|
||||||
|
return ocf_alock_is_locked_exclusively(alock, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ocf_cache_line_concurrency_suspended_no(struct ocf_alock *alock)
|
||||||
|
{
|
||||||
|
return ocf_alock_waitlist_count(alock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define ALLOCATOR_NAME_FMT "ocf_%s_cache_concurrency"
|
||||||
|
#define ALLOCATOR_NAME_MAX (sizeof(ALLOCATOR_NAME_FMT) + OCF_CACHE_NAME_SIZE)
|
||||||
|
|
||||||
|
int ocf_cache_line_concurrency_init(struct ocf_alock **self,
|
||||||
|
unsigned num_clines, ocf_cache_t cache)
|
||||||
|
{
|
||||||
|
char name[ALLOCATOR_NAME_MAX];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = snprintf(name, sizeof(name), ALLOCATOR_NAME_FMT,
|
||||||
|
ocf_cache_get_name(cache));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret >= ALLOCATOR_NAME_MAX)
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
|
return ocf_alock_init(self, num_clines, name, cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ocf_cache_line_concurrency_deinit(struct ocf_alock **self)
|
||||||
|
{
|
||||||
|
ocf_alock_deinit(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ocf_cache_line_concurrency_size_of(ocf_cache_t cache)
|
||||||
|
{
|
||||||
|
return ocf_alock_size(cache->device->collision_table_entries);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user