Skip to content

Instantly share code, notes, and snippets.

@dvyukov
Created October 28, 2015 04:53
Show Gist options
  • Save dvyukov/93c2d1775625a684cc11 to your computer and use it in GitHub Desktop.
Save dvyukov/93c2d1775625a684cc11 to your computer and use it in GitHub Desktop.
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
struct shm_t {
uint32_t head;
uint32_t alloc;
char data[0];
};
#define SHM_HEADER_SIZE 8
#define SHM_BLOCK_SIZE 8
#define SHM_BLOCK_ALIGNMENT 8
#define SHM_SIZE (1<<20)
void *shm_alloc(struct shm_t *shm, uint32_t size)
{
uint32_t alloc, new;
size = ((size+SHM_BLOCK_ALIGNMENT-1)&~(SHM_BLOCK_ALIGNMENT-1)) + SHM_BLOCK_SIZE;
alloc = __atomic_load_n(&shm->alloc, __ATOMIC_RELAXED);
for (;;) {
new = alloc + size;
if (new > SHM_SIZE-SHM_HEADER_SIZE)
return 0;
if (__atomic_compare_exchange_n(&shm->alloc, &alloc, new, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED))
return &shm->data[alloc + SHM_BLOCK_SIZE];
}
}
void shm_commit(struct shm_t *shm, void *block)
{
uint32_t *hdr;
hdr = (uint32_t*)((char*)block-SHM_BLOCK_SIZE);
*hdr = __atomic_load_n(&shm->head, __ATOMIC_ACQUIRE);
while (!__atomic_compare_exchange_n(&shm->head, hdr, (char*)block - &shm->data[0], 1, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE));
}
void shm_foreach(struct shm_t *shm, void (*f)(void*, void*), void *ctx)
{
uint32_t pos;
pos = __atomic_load_n(&shm->head, __ATOMIC_ACQUIRE);
while (pos) {
f(ctx, &shm->data[pos]);
pos = *(uint32_t*)&shm->data[pos-SHM_BLOCK_SIZE];
}
}
void print(void *ctx, void *b);
int main()
{
struct shm_t *shm;
void *b0, *b1, *b2;
shm = calloc(SHM_SIZE, 1);
b0 = shm_alloc(shm, 8);
b1 = shm_alloc(shm, 12);
b2 = shm_alloc(shm, 12);
((uint32_t*)b0)[0] = 1;
((uint32_t*)b0)[1] = 11;
((uint32_t*)b1)[0] = 2;
((uint32_t*)b1)[1] = 21;
((uint32_t*)b1)[2] = 22;
((uint32_t*)b2)[0] = 2;
((uint32_t*)b2)[1] = 31;
((uint32_t*)b2)[2] = 32;
shm_commit(shm, b1);
shm_commit(shm, b0);
shm_commit(shm, b2);
shm_foreach(shm, print, 0);
return 0;
}
void print(void *ctx, void *b)
{
uint32_t i, n;
n = *(uint32_t*)b;
printf("size=%d:", n);
for (i = 0; i < n; i++)
printf(" %d", ((uint32_t*)b)[i+1]);
printf("\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment