commit
0e3c5739c3
@ -0,0 +1,4 @@
|
|||||||
|
*.o
|
||||||
|
*~
|
||||||
|
*.a
|
||||||
|
*.so
|
@ -0,0 +1,39 @@
|
|||||||
|
SRC = $(wildcard src/*.c)
|
||||||
|
INCLUDE = include
|
||||||
|
|
||||||
|
CFLAGS = -Wall $(addprefix -I,$(INCLUDE)) --std=gnu11 -pedantic
|
||||||
|
CFLAGS+= -O3 -flto -fgraphite
|
||||||
|
|
||||||
|
LDFLAGS = -O3 -flto
|
||||||
|
|
||||||
|
OBJ:= obj
|
||||||
|
|
||||||
|
STATIC = $(addprefix $(OBJ)/static/,$(SRC:.c=.o))
|
||||||
|
SHARED = $(addprefix $(OBJ)/shared/,$(SRC:.c=.o))
|
||||||
|
|
||||||
|
BUILD = librc
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: dirs $(BUILD)
|
||||||
|
|
||||||
|
dirs:
|
||||||
|
@mkdir -p obj/{shared,static}/src
|
||||||
|
|
||||||
|
obj/static/%.o: %.c
|
||||||
|
$(CC) -c $< $(CFLAGS) -o $@
|
||||||
|
|
||||||
|
obj/shared/%.o: %.c
|
||||||
|
$(CC) -fPIC -c $< $(CFLAGS) -o $@
|
||||||
|
|
||||||
|
$(BUILD).a: $(STATIC)
|
||||||
|
ar rcs $@ $^
|
||||||
|
|
||||||
|
$(BUILD).so: $(SHARED)
|
||||||
|
$(CC) -shared $^ $(CFLAGS) -o $@ $(LDFLAGS)
|
||||||
|
strip $@
|
||||||
|
|
||||||
|
$(BUILD): $(BUILD).a $(BUILD).so
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(BUILD).{a,so}
|
||||||
|
rm -rf obj
|
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef _RC_H
|
||||||
|
#define _RC_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define _rc_restrict __restrict
|
||||||
|
extern "C" {
|
||||||
|
#else
|
||||||
|
#define _rc_restrict restrict
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#define _rc_attr(_)
|
||||||
|
#else
|
||||||
|
#define _rc_attr(v) __attribute__(v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct rc* rc_t;
|
||||||
|
|
||||||
|
void* _rc_restrict rc_malloc(size_t sz) _rc_attr((malloc, alloc_size(1), returns_nonnull));
|
||||||
|
void rc_free(void* ptr) _rc_attr((nonnull));
|
||||||
|
void* _rc_attr((may_alias)) rc_clone(void* ptr) _rc_attr((pure, nonnull, returns_nonnull));
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _RC_H */
|
@ -0,0 +1,74 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include <rc.h>
|
||||||
|
|
||||||
|
#define RC_CHK 0xabadcafe
|
||||||
|
|
||||||
|
struct rc {
|
||||||
|
uint32_t check;
|
||||||
|
_Atomic size_t refs;
|
||||||
|
|
||||||
|
uint8_t ptr[];
|
||||||
|
};
|
||||||
|
|
||||||
|
_rc_attr((noreturn)) static void panic(const char* string, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, string);
|
||||||
|
fprintf(stderr, "(librc) Fatal error: ");
|
||||||
|
vfprintf(stderr, string, args);
|
||||||
|
va_end(args);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
_rc_attr((noinline, noreturn, cold)) static void _fail_invptr()
|
||||||
|
{
|
||||||
|
panic("Invalid RC pointer");
|
||||||
|
}
|
||||||
|
|
||||||
|
_rc_attr((noinline, noreturn, cold)) static void _fail_malloc(size_t sz)
|
||||||
|
{
|
||||||
|
panic("malloc() failed to allocate %d bytes (%d + sizeof(struct rc))", sz+sizeof(struct rc), sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
_rc_attr((artificial, always_inline)) inline static rc_t ptr_rev(void* ptr)
|
||||||
|
{
|
||||||
|
if (!ptr) _fail_invptr();
|
||||||
|
return (rc_t)(((uint8_t*)ptr) - sizeof(struct rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
_rc_attr((nonnull)) inline static void rc_checkptr(const rc_t rc)
|
||||||
|
{
|
||||||
|
if (rc->check != RC_CHK) _fail_invptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
_rc_attr((malloc, alloc_size(1), returns_nonnull)) void* restrict rc_malloc(size_t sz)
|
||||||
|
{
|
||||||
|
register rc_t rc = malloc(sz + sizeof(struct rc));
|
||||||
|
|
||||||
|
if (!rc) _fail_malloc(sz);
|
||||||
|
|
||||||
|
rc->check = RC_CHK;
|
||||||
|
rc->refs = 1;
|
||||||
|
|
||||||
|
return (void*) rc->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
_rc_attr((nonnull)) void rc_free(void* ptr)
|
||||||
|
{
|
||||||
|
register rc_t rc = ptr_rev(ptr);
|
||||||
|
rc_checkptr(rc);
|
||||||
|
if (!--rc->refs) free(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
_rc_attr((pure, nonnull, returns_nonnull)) void* _rc_attr((may_alias)) rc_clone(void* ptr)
|
||||||
|
{
|
||||||
|
register rc_t rc = ptr_rev(ptr);
|
||||||
|
rc_checkptr(rc);
|
||||||
|
++rc->refs;
|
||||||
|
return ptr;
|
||||||
|
}
|
Loading…
Reference in new issue