Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Entire SysV::Integer code and associated shared libraries #67

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ext/semian/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
have_func 'rb_thread_blocking_region'
have_func 'rb_thread_call_without_gvl'

$CFLAGS = "-D_GNU_SOURCE -Werror -Wall "
$CFLAGS = "-D_GNU_SOURCE -Werror -Wall -std=c99 "
if ENV.key?('DEBUG')
$CFLAGS << "-O0 -g"
else
Expand Down
45 changes: 9 additions & 36 deletions ext/semian/semian.c
Original file line number Diff line number Diff line change
@@ -1,38 +1,6 @@
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>

#include <ruby.h>
#include <ruby/util.h>
#include <ruby/io.h>

#include <openssl/sha.h>

#include <stdio.h>

union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};

#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) && defined(HAVE_RUBY_THREAD_H)
// 2.0
#include <ruby/thread.h>
#define WITHOUT_GVL(fn,a,ubf,b) rb_thread_call_without_gvl((fn),(a),(ubf),(b))
#elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
// 1.9
typedef VALUE (*my_blocking_fn_t)(void*);
#define WITHOUT_GVL(fn,a,ubf,b) rb_thread_blocking_region((my_blocking_fn_t)(fn),(a),(ubf),(b))
#endif
#include "semian.h"

static ID id_timeout;
static VALUE eSyscall, eTimeout, eInternal;
static int system_max_semaphore_count;

static const int kIndexTickets = 0;
Expand All @@ -48,7 +16,7 @@ typedef struct {
char *name;
} semian_resource_t;

static key_t
key_t
generate_key(const char *name)
{
union {
Expand All @@ -67,7 +35,7 @@ ms_to_timespec(long ms, struct timespec *ts)
ts->tv_nsec = (ms % 1000) * 1000000;
}

static void
void
raise_semian_syscall_error(const char *syscall, int error_num)
{
rb_raise(eSyscall, "%s failed, errno: %d (%s)", syscall, error_num, strerror(error_num));
Expand Down Expand Up @@ -115,7 +83,7 @@ semian_resource_alloc(VALUE klass)
return obj;
}

static void
void
set_semaphore_permissions(int sem_id, int permissions)
{
union semun sem_opts;
Expand Down Expand Up @@ -447,6 +415,9 @@ semian_resource_id(VALUE self)
return LONG2FIX(res->sem_id);
}


void Init_semian_shm_object();

void Init_semian()
{
VALUE cSemian, cResource;
Expand Down Expand Up @@ -504,4 +475,6 @@ void Init_semian()

/* Maximum number of tickets available on this system. */
rb_define_const(cSemian, "MAX_TICKETS", INT2FIX(system_max_semaphore_count));

Init_semian_shm_object();
}
48 changes: 48 additions & 0 deletions ext/semian/semian.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>

#include <ruby.h>
#include <ruby/util.h>
#include <ruby/io.h>

#include <openssl/sha.h>

#include <stdio.h>

#include <sys/shm.h>
#include <unistd.h>

#include <math.h>

union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};

#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) && defined(HAVE_RUBY_THREAD_H)
// 2.0
#include <ruby/thread.h>
#define WITHOUT_GVL(fn,a,ubf,b) rb_thread_call_without_gvl((fn),(a),(ubf),(b))
#elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
// 1.9
typedef VALUE (*my_blocking_fn_t)(void*);
#define WITHOUT_GVL(fn,a,ubf,b) rb_thread_blocking_region((my_blocking_fn_t)(fn),(a),(ubf),(b))
#endif

VALUE eSyscall, eTimeout, eInternal;

key_t
generate_key(const char *name);

void
raise_semian_syscall_error(const char *syscall, int error_num);

void
set_semaphore_permissions(int sem_id, int permissions);
105 changes: 105 additions & 0 deletions ext/semian/semian_integer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "semian_shared_memory_object.h"

typedef struct {
int value;
} semian_int;

static void semian_integer_initialize_memory (size_t byte_size, void *dest, void *prev_data, size_t prev_data_byte_size);
static VALUE semian_integer_bind_initialize_memory_callback(VALUE self);
static VALUE semian_integer_get_value(VALUE self);
static VALUE semian_integer_set_value(VALUE self, VALUE num);
static VALUE semian_integer_increment(int argc, VALUE *argv, VALUE self);

static void
semian_integer_initialize_memory (size_t byte_size, void *dest, void *prev_data, size_t prev_data_byte_size)
{
semian_int *ptr = dest;
semian_int *old = prev_data;
if (prev_data){
ptr->value = old->value;
} else {
ptr->value=0;
}
}

static VALUE
semian_integer_bind_initialize_memory_callback(VALUE self)
{
semian_shm_object *ptr;
TypedData_Get_Struct(self, semian_shm_object, &semian_shm_object_type, ptr);
ptr->initialize_memory = &semian_integer_initialize_memory;
return self;
}

static VALUE
semian_integer_get_value(VALUE self)
{
semian_shm_object *ptr;
TypedData_Get_Struct(self, semian_shm_object, &semian_shm_object_type, ptr);
if (0 == ptr->shm_address)
return Qnil;
int value = ((semian_int *)(ptr->shm_address))->value;
return INT2NUM(value);
}

static VALUE
semian_integer_set_value(VALUE self, VALUE num)
{
semian_shm_object *ptr;
TypedData_Get_Struct(self, semian_shm_object, &semian_shm_object_type, ptr);
if (0 == ptr->shm_address)
return Qnil;
if (TYPE(num) != T_FIXNUM && TYPE(num) != T_FLOAT)
return Qnil;
((semian_int *)(ptr->shm_address))->value = NUM2INT(num);
return num;
}

static VALUE
semian_integer_reset(VALUE self)
{
return semian_integer_set_value(self, INT2NUM(0));
}

static VALUE
semian_integer_increment(int argc, VALUE *argv, VALUE self)
{
VALUE num;
rb_scan_args(argc, argv, "01", &num);
if (num == Qnil)
num = INT2NUM(1);

semian_shm_object *ptr;
TypedData_Get_Struct(self, semian_shm_object, &semian_shm_object_type, ptr);
if (0 == ptr->shm_address)
return Qnil;
if (TYPE(num) != T_FIXNUM && TYPE(num) != T_FLOAT)
return Qnil;
((semian_int *)(ptr->shm_address))->value += NUM2INT(num);
return self;
}

static VALUE
semian_integer_calculate_byte_size(VALUE klass)
{
return SIZET2NUM(sizeof(int));
}

void
Init_semian_integer (void)
{
// Bind methods to Integer
VALUE cSemianModule = rb_const_get(rb_cObject, rb_intern("Semian"));
VALUE cSysVSharedMemory = rb_const_get(cSemianModule, rb_intern("SysVSharedMemory"));
VALUE cSysVModule = rb_const_get(cSemianModule, rb_intern("SysV"));
VALUE cInteger = rb_const_get(cSysVModule, rb_intern("Integer"));

semian_shm_object_replace_alloc(cSysVSharedMemory, cInteger);

rb_define_private_method(cInteger, "bind_initialize_memory_callback", semian_integer_bind_initialize_memory_callback, 0);
define_method_with_synchronize(cInteger, "value", semian_integer_get_value, 0);
define_method_with_synchronize(cInteger, "value=", semian_integer_set_value, 1);
define_method_with_synchronize(cInteger, "reset", semian_integer_reset, 0);
define_method_with_synchronize(cInteger, "increment", semian_integer_increment, -1);
rb_define_method(cInteger, "calculate_byte_size", semian_integer_calculate_byte_size, 0);
}
Loading