From b3bb10e19ed2de52a881fb0ea98e0292e6ebce65 Mon Sep 17 00:00:00 2001 From: Cyrille Henry Date: Wed, 31 Oct 2012 22:59:51 +0000 Subject: initial commit of a lib dedicated to share memory management svn path=/trunk/externals/share_mem/; revision=16503 --- shmem.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 shmem.c (limited to 'shmem.c') diff --git a/shmem.c b/shmem.c new file mode 100644 index 0000000..404d795 --- /dev/null +++ b/shmem.c @@ -0,0 +1,171 @@ +#include "m_pd.h" +#include +#include +#include + +typedef struct shmem +{ + t_object x_obj; + int segment_id; + t_float *share_memory; + int segment_size; +} t_shmem; + +inline t_float min(t_float x1,t_float x2) +{ + if (x1 <= x2) { + return x1; + } else { + return x2; + } +} + +void shmem_set(t_shmem *x, t_symbol *unused, int argc, t_atom *argv) +{ + + t_garray *a; + int npoints; + int array_offset; + t_word *vec; + int i, index_max, shmem_offset; + + if (argc <= 1) { + pd_error(x, "shmem usage : memset offset data (data can be a float, a list, or a table name)"); + return; + } + if (argv[0].a_type != A_FLOAT) { + pd_error(x, "shmem usage : memset offset data (data can be a float, a list, or a table name)"); + return; + } + + shmem_offset = atom_getfloatarg(0,argc,argv); + if (shmem_offset < 0) shmem_offset=0; + + if (argv[1].a_type == A_SYMBOL) { // argument is an arrayname + t_symbol *s = atom_getsymbolarg(1,argc,argv); + if (!(a = (t_garray *)pd_findbyclass(s, garray_class))) + pd_error(x, "%s: no such array", s->s_name); + else if (!garray_getfloatwords(a, &npoints, &vec)) + pd_error(x, "%s: bad template for tabread", s->s_name); + else { + if (argc == 2) { // memset index_mem arrayname + index_max = min(x->segment_size-shmem_offset,npoints); + // post("i=%d", index_max); + for (i=0; ishare_memory[i+shmem_offset] = vec[i].w_float; + } + else if (argc == 3) { // memset index_mem arrayname array_offset + array_offset = atom_getfloatarg(2,argc,argv); + index_max = min(x->segment_size-shmem_offset,npoints-array_offset); + //post("i=%d", x->segment_size-shmem_offset); + //post("i=%d", npoints); + //post("i=%d", index_max); + for (i=0; ishare_memory[i+shmem_offset] = vec[i+array_offset].w_float; + } + } + } + else if (argv[1].a_type == A_FLOAT) { // argument is a float + index_max = x->segment_size - shmem_offset; + if (index_max > argc-1) index_max = argc-1; + for (i=0; ishare_memory[i+shmem_offset]=atom_getfloatarg(i+1, argc, argv); + } +} + +void shmem_dump(t_shmem *x, t_symbol *unused, int argc, t_atom *argv) +{ + int i, vecsize, index_max, shmem_offset; + t_garray *a; + t_word *vec; + + if (argc == 0) { + pd_error(x, "shmem usage : memdump offset dest (dest can be nothing (outlet), or a table name)"); + return; + } + if (argv[0].a_type != A_FLOAT) { + pd_error(x, "shmem usage : memdump offset dest (dest can be nothing (outlet), or a table name)"); + return; + } + shmem_offset = atom_getfloatarg(0,argc,argv); + if (shmem_offset < 0) shmem_offset = 0; + if (shmem_offset > x->segment_size-1) i = x->segment_size-1; + // post("i=%d", offset); + + if (argc == 1) + outlet_float(x->x_obj.ob_outlet, x->share_memory[shmem_offset]); + else if (argv[1].a_type == A_SYMBOL) { // argument is an arrayname + t_symbol *s = atom_getsymbolarg(1,argc,argv); + if (!(a = (t_garray *)pd_findbyclass(s, garray_class))) + pd_error(x, "%s: no such array", s->s_name); + else { + if (!garray_getfloatwords(a, &vecsize, &vec)) + pd_error(x, "%s: bad template for tabwrite", s->s_name); + else { + index_max = x->segment_size-shmem_offset; + if (index_max > vecsize) + index_max = vecsize; + // post("i=%d", index_max); + for (i=0; ishare_memory[i+shmem_offset]; + } + garray_redraw(a); + } + } +} + +t_class *shmem_class; + +void *shmem_new( t_floatarg id, t_floatarg size) +{ + struct shmid_ds shmbuffer; + // post ("id, size: %f, %f", id, size); + t_shmem *x = (t_shmem *)pd_new(shmem_class); + + x->segment_size = (int)size; + x->segment_id = shmget ((int)id, sizeof(t_float)*x->segment_size, + IPC_CREAT | S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH); + if(x->segment_id>0) { + x->share_memory = (t_float*) shmat (x->segment_id, 0, 0); + // post("shmem memory attached at address %p\n", x->share_memory); + + shmctl (x->segment_id, IPC_STAT, &shmbuffer); + // post ("segment size: %d\n", shmbuffer.shm_segsz); + + if ((int)shmbuffer.shm_segsz < (int)sizeof(t_float)*x->segment_size) { + // there was a problem, set object meme size to 0 + error("could not allocate shmem memory Id : %d, size %d", (int)id, x->segment_size ); + x->segment_size = 0; + } + } + else { + error("could not allocate shmem memory Id : %d, size %d", (int)id, x->segment_size ); + x->segment_size = 0; + } + + outlet_new(&x->x_obj, 0); + return (void *)x; +} + +void shmem_free(t_shmem *x) +{ + shmdt (x->share_memory); + shmctl (x->segment_id, IPC_RMID, 0); +} + +void shmem_clear(t_shmem *x) +{ + int i; + for (i=0; isegment_size; i++) + x->share_memory[i] = 0; +} + +void shmem_setup(void) +{ + shmem_class = class_new(gensym("shmem"), (t_newmethod)shmem_new, (t_method)shmem_free, + sizeof(t_shmem), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(shmem_class, (t_method)shmem_set, gensym("memset"), A_GIMME, 0); + class_addmethod(shmem_class, (t_method)shmem_dump, gensym("memdump"), A_GIMME, 0); + class_addmethod(shmem_class, (t_method)shmem_clear, gensym("memclear"), 0); +} + -- cgit v1.2.1