-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpercpu.c
30 lines (28 loc) · 1.02 KB
/
percpu.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdlib.h>
#include <stdatomic.h>
#include <string.h>
#include <unistd.h>
#include "percpu.h"
struct percpu *percpu_new(size_t bucket_size, void (*init_fn)(void *ptr))
{
/* try to figure out the proper setup. idea here is that from 8 threads
* up, the system is likely to share highest-level caches between two
* sibling CPUs.
*/
int n_cpus = sysconf(_SC_NPROCESSORS_ONLN), shift = n_cpus >= 8 ? 1 : 0, n_buckets = n_cpus >> shift;
bucket_size = (bucket_size + 63) & ~63;
size_t base_size = (sizeof(struct percpu) + sizeof(void *) * n_buckets + 63) & ~63;
struct percpu *p = aligned_alloc(64, base_size + bucket_size * n_buckets);
if(p == NULL) return NULL;
*p = (struct percpu){ .n_buckets = n_buckets, .shift = shift };
for(int i=0; i < n_buckets; i++) {
p->buckets[i] = (void *)p + base_size + bucket_size * i;
memset(p->buckets[i], '\0', bucket_size);
if(init_fn != NULL) (*init_fn)(p->buckets[i]);
}
atomic_thread_fence(memory_order_release);
return p;
}
void percpu_free(struct percpu *p) {
free(p);
}