#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); }