aboutsummaryrefslogtreecommitdiff
path: root/shmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'shmem.c')
-rw-r--r--shmem.c171
1 files changed, 171 insertions, 0 deletions
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 <stdio.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+
+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; i<index_max; i++)
+ x->share_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; i<index_max; i++)
+ x->share_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; i<index_max ; i++)
+ x->share_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; i<index_max; i++)
+ vec[i].w_float = x->share_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; i<x->segment_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);
+}
+