Skip to content

Commit 8f92d31

Browse files
committed
a
1 parent c93cba5 commit 8f92d31

File tree

10 files changed

+171
-128
lines changed

10 files changed

+171
-128
lines changed

src/critnib/critnib.c

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2023-2024 Intel Corporation
3+
* Copyright (C) 2023-2025 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -133,24 +133,6 @@ struct critnib {
133133
struct utils_mutex_t mutex; /* writes/removes */
134134
};
135135

136-
/*
137-
* atomic load
138-
*/
139-
static void load(void *src, void *dst) {
140-
utils_atomic_load_acquire((word *)src, (word *)dst);
141-
}
142-
143-
static void load64(uint64_t *src, uint64_t *dst) {
144-
utils_atomic_load_acquire(src, dst);
145-
}
146-
147-
/*
148-
* atomic store
149-
*/
150-
static void store(void *dst, void *src) {
151-
utils_atomic_store_release((word *)dst, (word)src);
152-
}
153-
154136
/*
155137
* internal: is_leaf -- check tagged pointer for leafness
156138
*/
@@ -343,10 +325,8 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
343325

344326
struct critnib_node *n = c->root;
345327
if (!n) {
346-
store(&c->root, kn);
347-
328+
utils_atomic_store_release_ptr(&c->root, kn);
348329
utils_mutex_unlock(&c->mutex);
349-
350330
return 0;
351331
}
352332

@@ -361,7 +341,8 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
361341

362342
if (!n) {
363343
n = prev;
364-
store(&n->child[slice_index(key, n->shift)], kn);
344+
utils_atomic_store_release_ptr(&n->child[slice_index(key, n->shift)],
345+
kn);
365346

366347
utils_mutex_unlock(&c->mutex);
367348

@@ -406,7 +387,7 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
406387
m->child[slice_index(path, sh)] = n;
407388
m->shift = sh;
408389
m->path = key & path_mask(sh);
409-
store(parent, m);
390+
utils_atomic_store_release_ptr(parent, m);
410391

411392
utils_mutex_unlock(&c->mutex);
412393

@@ -427,7 +408,8 @@ void *critnib_remove(struct critnib *c, word key) {
427408
goto not_found;
428409
}
429410

430-
word del = (utils_atomic_increment(&c->remove_count) - 1) % DELETED_LIFE;
411+
word del =
412+
(utils_atomic_increment_u64(&c->remove_count) - 1) % DELETED_LIFE;
431413
free_node(c, c->pending_del_nodes[del]);
432414
free_leaf(c, c->pending_del_leaves[del]);
433415
c->pending_del_nodes[del] = NULL;
@@ -436,7 +418,7 @@ void *critnib_remove(struct critnib *c, word key) {
436418
if (is_leaf(n)) {
437419
k = to_leaf(n);
438420
if (k->key == key) {
439-
store(&c->root, NULL);
421+
utils_atomic_store_release_ptr(&c->root, NULL);
440422
goto del_leaf;
441423
}
442424

@@ -466,7 +448,7 @@ void *critnib_remove(struct critnib *c, word key) {
466448
goto not_found;
467449
}
468450

469-
store(&n->child[slice_index(key, n->shift)], NULL);
451+
utils_atomic_store_release_ptr(&n->child[slice_index(key, n->shift)], NULL);
470452

471453
/* Remove the node if there's only one remaining child. */
472454
int ochild = -1;
@@ -482,7 +464,7 @@ void *critnib_remove(struct critnib *c, word key) {
482464

483465
ASSERTne(ochild, -1);
484466

485-
store(n_parent, n->child[ochild]);
467+
utils_atomic_store_release_ptr(n_parent, n->child[ochild]);
486468
c->pending_del_nodes[del] = n;
487469

488470
del_leaf:
@@ -511,22 +493,23 @@ void *critnib_get(struct critnib *c, word key) {
511493
do {
512494
struct critnib_node *n;
513495

514-
load64(&c->remove_count, &wrs1);
515-
load(&c->root, &n);
496+
utils_atomic_load_acquire_u64(&c->remove_count, &wrs1);
497+
utils_atomic_load_acquire_ptr(&c->root, (void **)&n);
516498

517499
/*
518500
* critbit algorithm: dive into the tree, looking at nothing but
519501
* each node's critical bit^H^H^Hnibble. This means we risk
520502
* going wrong way if our path is missing, but that's ok...
521503
*/
522504
while (n && !is_leaf(n)) {
523-
load(&n->child[slice_index(key, n->shift)], &n);
505+
utils_atomic_load_acquire_ptr(&n->child[slice_index(key, n->shift)],
506+
(void **)&n);
524507
}
525508

526509
/* ... as we check it at the end. */
527510
struct critnib_leaf *k = to_leaf(n);
528511
res = (n && k->key == key) ? k->value : NULL;
529-
load64(&c->remove_count, &wrs2);
512+
utils_atomic_load_acquire_u64(&c->remove_count, &wrs2);
530513
} while (wrs1 + DELETED_LIFE <= wrs2);
531514

532515
return res;
@@ -597,7 +580,7 @@ static struct critnib_leaf *find_le(struct critnib_node *__restrict n,
597580
/* recursive call: follow the path */
598581
{
599582
struct critnib_node *m;
600-
load(&n->child[nib], &m);
583+
utils_atomic_load_acquire_ptr(&n->child[nib], (void **)&m);
601584
struct critnib_leaf *k = find_le(m, key);
602585
if (k) {
603586
return k;
@@ -611,7 +594,7 @@ static struct critnib_leaf *find_le(struct critnib_node *__restrict n,
611594
*/
612595
for (; nib > 0; nib--) {
613596
struct critnib_node *m;
614-
load(&n->child[nib - 1], &m);
597+
utils_atomic_load_acquire_ptr(&n->child[nib - 1], (void **)&m);
615598
if (m) {
616599
n = m;
617600
if (is_leaf(n)) {
@@ -635,12 +618,12 @@ void *critnib_find_le(struct critnib *c, word key) {
635618
void *res;
636619

637620
do {
638-
load64(&c->remove_count, &wrs1);
621+
utils_atomic_load_acquire_u64(&c->remove_count, &wrs1);
639622
struct critnib_node *n; /* avoid a subtle TOCTOU */
640-
load(&c->root, &n);
623+
utils_atomic_load_acquire_ptr(&c->root, (void **)&n);
641624
struct critnib_leaf *k = n ? find_le(n, key) : NULL;
642625
res = k ? k->value : NULL;
643-
load64(&c->remove_count, &wrs2);
626+
utils_atomic_load_acquire_u64(&c->remove_count, &wrs2);
644627
} while (wrs1 + DELETED_LIFE <= wrs2);
645628

646629
return res;
@@ -694,7 +677,7 @@ static struct critnib_leaf *find_ge(struct critnib_node *__restrict n,
694677
unsigned nib = slice_index(key, n->shift);
695678
{
696679
struct critnib_node *m;
697-
load(&n->child[nib], &m);
680+
utils_atomic_load_acquire_ptr(&n->child[nib], (void **)&m);
698681
struct critnib_leaf *k = find_ge(m, key);
699682
if (k) {
700683
return k;
@@ -703,7 +686,7 @@ static struct critnib_leaf *find_ge(struct critnib_node *__restrict n,
703686

704687
for (; nib < NIB; nib++) {
705688
struct critnib_node *m;
706-
load(&n->child[nib + 1], &m);
689+
utils_atomic_load_acquire_ptr(&n->child[nib + 1], (void **)&m);
707690
if (m) {
708691
n = m;
709692
if (is_leaf(n)) {
@@ -741,17 +724,18 @@ int critnib_find(struct critnib *c, uintptr_t key, enum find_dir_t dir,
741724
}
742725

743726
do {
744-
load64(&c->remove_count, &wrs1);
727+
utils_atomic_load_acquire_u64(&c->remove_count, &wrs1);
745728
struct critnib_node *n;
746-
load(&c->root, &n);
729+
utils_atomic_load_acquire_ptr(&c->root, (void **)&n);
747730

748731
if (dir < 0) {
749732
k = find_le(n, key);
750733
} else if (dir > 0) {
751734
k = find_ge(n, key);
752735
} else {
753736
while (n && !is_leaf(n)) {
754-
load(&n->child[slice_index(key, n->shift)], &n);
737+
utils_atomic_load_acquire_ptr(
738+
&n->child[slice_index(key, n->shift)], (void **)&n);
755739
}
756740

757741
struct critnib_leaf *kk = to_leaf(n);
@@ -761,7 +745,7 @@ int critnib_find(struct critnib *c, uintptr_t key, enum find_dir_t dir,
761745
_rkey = k->key;
762746
_rvalue = k->value;
763747
}
764-
load64(&c->remove_count, &wrs2);
748+
utils_atomic_load_acquire_u64(&c->remove_count, &wrs2);
765749
} while (wrs1 + DELETED_LIFE <= wrs2);
766750

767751
if (k) {

src/ipc_cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ umf_result_t umfIpcOpenedCacheGet(ipc_opened_cache_handle_t cache,
232232

233233
exit:
234234
if (ret == UMF_RESULT_SUCCESS) {
235-
utils_atomic_increment(&entry->ref_count);
235+
utils_atomic_increment_u64(&entry->ref_count);
236236
*retEntry = &entry->value;
237237
}
238238

src/libumf.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424

2525
umf_memory_tracker_handle_t TRACKER = NULL;
2626

27-
static unsigned long long umfRefCount = 0;
27+
static uint64_t umfRefCount = 0;
2828

2929
int umfInit(void) {
30-
if (utils_fetch_and_add64(&umfRefCount, 1) == 0) {
30+
if (utils_fetch_and_add_u64(&umfRefCount, 1) == 0) {
3131
utils_log_init();
3232
TRACKER = umfMemoryTrackerCreate();
3333
if (!TRACKER) {
@@ -54,7 +54,7 @@ int umfInit(void) {
5454
}
5555

5656
void umfTearDown(void) {
57-
if (utils_fetch_and_add64(&umfRefCount, -1) == 1) {
57+
if (utils_fetch_and_add_u64(&umfRefCount, -1) == 1) {
5858
#if !defined(_WIN32) && !defined(UMF_NO_HWLOC)
5959
umfMemspaceHostAllDestroy();
6060
umfMemspaceHighestCapacityDestroy();

src/pool/pool_disjoint.c

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "provider/provider_tracking.h"
2121
#include "uthash/utlist.h"
2222
#include "utils_common.h"
23+
#include "utils_concurrency.h"
2324
#include "utils_log.h"
2425
#include "utils_math.h"
2526

@@ -34,7 +35,6 @@
3435
// Forward declarations
3536
static void bucket_update_stats(bucket_t *bucket, int in_use, int in_pool);
3637
static bool bucket_can_pool(bucket_t *bucket);
37-
static void bucket_decrement_pool(bucket_t *bucket);
3838
static slab_list_item_t *bucket_get_avail_slab(bucket_t *bucket,
3939
bool *from_pool);
4040

@@ -316,6 +316,7 @@ static void bucket_free_chunk(bucket_t *bucket, void *ptr, slab_t *slab,
316316
assert(slab_it->val != NULL);
317317
pool_unregister_slab(bucket->pool, slab_it->val);
318318
DL_DELETE(bucket->available_slabs, slab_it);
319+
assert(bucket->available_slabs_num > 0);
319320
bucket->available_slabs_num--;
320321
destroy_slab(slab_it->val);
321322
}
@@ -381,10 +382,17 @@ static slab_list_item_t *bucket_get_avail_slab(bucket_t *bucket,
381382
// Allocation from existing slab is treated as from pool for statistics.
382383
*from_pool = true;
383384
if (slab->num_chunks_allocated == 0) {
385+
assert(bucket->chunked_slabs_in_pool > 0);
386+
assert(bucket->shared_limits->total_size >=
387+
bucket_slab_alloc_size(bucket));
384388
// If this was an empty slab, it was in the pool.
385389
// Now it is no longer in the pool, so update count.
386390
--bucket->chunked_slabs_in_pool;
387-
bucket_decrement_pool(bucket);
391+
CACHE_ALIGNED size_t size_to_add =
392+
-(long long)bucket_slab_alloc_size(bucket);
393+
utils_fetch_and_add_u64(&bucket->shared_limits->total_size,
394+
size_to_add);
395+
bucket_update_stats(bucket, 1, -1);
388396
}
389397
}
390398

@@ -420,36 +428,26 @@ static void bucket_update_stats(bucket_t *bucket, int in_use, int in_pool) {
420428
in_pool * bucket_slab_alloc_size(bucket);
421429
}
422430

423-
static void bucket_decrement_pool(bucket_t *bucket) {
424-
bucket_update_stats(bucket, 1, -1);
425-
utils_fetch_and_add64(&bucket->shared_limits->total_size,
426-
-(long long)bucket_slab_alloc_size(bucket));
427-
}
428-
429431
static bool bucket_can_pool(bucket_t *bucket) {
430432
size_t new_free_slabs_in_bucket;
431433

432434
new_free_slabs_in_bucket = bucket->chunked_slabs_in_pool + 1;
433435

434436
// we keep at most params.capacity slabs in the pool
435437
if (bucket_max_pooled_slabs(bucket) >= new_free_slabs_in_bucket) {
436-
size_t pool_size = 0;
437-
utils_atomic_load_acquire(&bucket->shared_limits->total_size,
438-
&pool_size);
439-
while (true) {
440-
size_t new_pool_size = pool_size + bucket_slab_alloc_size(bucket);
441-
442-
if (bucket->shared_limits->max_size < new_pool_size) {
443-
break;
444-
}
445-
446-
if (utils_compare_exchange(&bucket->shared_limits->total_size,
447-
&pool_size, &new_pool_size)) {
448-
++bucket->chunked_slabs_in_pool;
449-
450-
bucket_update_stats(bucket, -1, 1);
451-
return true;
452-
}
438+
439+
CACHE_ALIGNED size_t size_to_add = bucket_slab_alloc_size(bucket);
440+
size_t previous_size = utils_fetch_and_add_u64(
441+
&bucket->shared_limits->total_size, size_to_add);
442+
443+
if (previous_size + size_to_add <= bucket->shared_limits->max_size) {
444+
445+
++bucket->chunked_slabs_in_pool;
446+
bucket_update_stats(bucket, -1, 1);
447+
return true;
448+
} else {
449+
utils_fetch_and_add_u64(&bucket->shared_limits->total_size,
450+
-size_to_add);
453451
}
454452
}
455453

@@ -895,7 +893,8 @@ umf_memory_pool_ops_t *umfDisjointPoolOps(void) {
895893

896894
umf_disjoint_pool_shared_limits_t *
897895
umfDisjointPoolSharedLimitsCreate(size_t max_size) {
898-
umf_disjoint_pool_shared_limits_t *ptr = umf_ba_global_alloc(sizeof(*ptr));
896+
umf_disjoint_pool_shared_limits_t *ptr =
897+
umf_ba_global_aligned_alloc(sizeof(*ptr), 64);
899898
if (ptr == NULL) {
900899
LOG_ERR("cannot allocate memory for disjoint pool shared limits");
901900
return NULL;

src/pool/pool_disjoint_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ typedef struct slab_t {
101101
} slab_t;
102102

103103
typedef struct umf_disjoint_pool_shared_limits_t {
104+
CACHE_ALIGNED size_t total_size; // requires atomic access
104105
size_t max_size;
105-
size_t total_size; // requires atomic access
106106
} umf_disjoint_pool_shared_limits_t;
107107

108108
typedef struct umf_disjoint_pool_params_t {

src/provider/provider_os_memory.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,7 @@ static membind_t membindFirst(os_memory_provider_t *provider, void *addr,
934934

935935
if (provider->mode == UMF_NUMA_MODE_INTERLEAVE) {
936936
assert(provider->part_size != 0);
937-
size_t s = utils_fetch_and_add64(&provider->alloc_sum, size);
937+
size_t s = utils_fetch_and_add_u64(&provider->alloc_sum, size);
938938
membind.node = (s / provider->part_size) % provider->nodeset_len;
939939
membind.bitmap = provider->nodeset[membind.node];
940940
membind.bind_size = ALIGN_UP(provider->part_size, membind.page_size);

src/provider/provider_tracking.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ static umf_result_t trackingGetIpcHandle(void *provider, const void *ptr,
565565
return ret;
566566
}
567567

568-
cache_value->handle_id = utils_atomic_increment(&IPC_HANDLE_ID);
568+
cache_value->handle_id = utils_atomic_increment_u64(&IPC_HANDLE_ID);
569569
cache_value->ipcDataSize = ipcDataSize;
570570

571571
int insRes = critnib_insert(p->ipcCache, (uintptr_t)ptr,
@@ -703,18 +703,20 @@ static umf_result_t trackingOpenIpcHandle(void *provider, void *providerIpcData,
703703
assert(cache_entry != NULL);
704704

705705
void *mapped_ptr = NULL;
706-
utils_atomic_load_acquire(&(cache_entry->mapped_base_ptr), &mapped_ptr);
706+
utils_atomic_load_acquire_ptr(&(cache_entry->mapped_base_ptr),
707+
(void **)&mapped_ptr);
707708
if (mapped_ptr == NULL) {
708709
utils_mutex_lock(&(cache_entry->mmap_lock));
709-
utils_atomic_load_acquire(&(cache_entry->mapped_base_ptr), &mapped_ptr);
710+
utils_atomic_load_acquire_ptr(&(cache_entry->mapped_base_ptr),
711+
(void **)&mapped_ptr);
710712
if (mapped_ptr == NULL) {
711713
ret = upstreamOpenIPCHandle(p, providerIpcData,
712714
ipcUmfData->baseSize, &mapped_ptr);
713715
if (ret == UMF_RESULT_SUCCESS) {
714716
// Put to the cache
715717
cache_entry->mapped_size = ipcUmfData->baseSize;
716-
utils_atomic_store_release(&(cache_entry->mapped_base_ptr),
717-
mapped_ptr);
718+
utils_atomic_store_release_ptr(&(cache_entry->mapped_base_ptr),
719+
mapped_ptr);
718720
}
719721
}
720722
utils_mutex_unlock(&(cache_entry->mmap_lock));

0 commit comments

Comments
 (0)