summaryrefslogtreecommitdiff
path: root/libtrivfs
diff options
context:
space:
mode:
Diffstat (limited to 'libtrivfs')
-rw-r--r--libtrivfs/cntl-classes.c22
-rw-r--r--libtrivfs/dyn-classes.c269
-rw-r--r--libtrivfs/protid-classes.c22
3 files changed, 313 insertions, 0 deletions
diff --git a/libtrivfs/cntl-classes.c b/libtrivfs/cntl-classes.c
new file mode 100644
index 00000000..81dd7e1e
--- /dev/null
+++ b/libtrivfs/cntl-classes.c
@@ -0,0 +1,22 @@
+/* Defaults for TRIVFS_CNTL_[N]PORTCLASSES
+
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "trivfs.h"
+
+struct port_class *trivfs_cntl_portclasses[1] = { 0 };
+int trivfs_cntl_nportclasses = 0;
diff --git a/libtrivfs/dyn-classes.c b/libtrivfs/dyn-classes.c
new file mode 100644
index 00000000..5f73f8f3
--- /dev/null
+++ b/libtrivfs/dyn-classes.c
@@ -0,0 +1,269 @@
+/* Dynamically allocated port classes/buckets recognized by trivfs
+
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Auxiliary info for each vector element. */
+struct aux
+{
+ void (*free_el)();
+ unsigned refs;
+};
+
+/* Vectors of dynamically allocated port classes/buckets. */
+
+/* Protid port classes. */
+struct port_class **trivfs_dynamic_protid_port_classes = 0;
+size_t trivfs_num_dynamic_protid_port_classes = 0;
+static struct aux *dynamic_protid_port_classes_aux = 0;
+static size_t dynamic_protid_port_classes_sz = 0;
+
+/* Control port classes. */
+struct port_class **trivfs_dynamic_control_port_classes = 0;
+size_t trivfs_num_dynamic_control_port_classes = 0;
+static struct aux *dynamic_control_port_classes_aux = 0;
+static size_t dynamic_control_port_classes_sz = 0;
+
+/* Port buckets. */
+struct port_bucket **trivfs_dynamic_port_buckets = 0;
+size_t trivfs_num_dynamic_port_buckets = 0;
+static struct aux *dynamic_port_buckets_aux = 0;
+static size_t dynamic_port_buckets_sz = 0;
+
+/* Lock used to control access to all the above vectors. */
+static struct mutex dyn_lock = MUTEX_INITIALIZER;
+
+/* Add EL to the vector pointed to by VEC_V, which should point to a vector
+ of pointers of some type, and has a length stored in *SZ; If there's
+ already a pointer to EL in VEC_V, nothing will actually be added, but the
+ reference count for that element will be increased. *NUM is the actual
+ number of non-null elements in the vector, and will be incremented if
+ something is actually added. AUX_VEC is a pointer to a vector of struct
+ aux elements, that contains information parralleling VEC_V. FREE_EL, if
+ non-zero, should be a function that takes a single argument of the same
+ type as EL, and deallocates it; this function is called in the following
+ cases: (1) An error is encountered trying to grow one of the vectors, (2)
+ when the element is eventually freed by drop_el. */
+static error_t
+add_el (void *el, void (*free_el)(),
+ void *vec_v, struct aux **aux_vec,
+ size_t *sz, size_t *num)
+{
+ int i;
+ size_t new_sz;
+ void ***vec, **new_vec;
+ struct aux *new_aux_vec;
+
+ if (! el)
+ return ENOMEM;
+
+ mutex_lock (&dyn_lock);
+
+ vec = vec_v;
+
+ for (i = 0; i < *sz; i++)
+ if (! (*vec)[i])
+ {
+ (*vec)[i] = el;
+ (*aux_vec)[i].free_el = free_el;
+ (*aux_vec)[i].refs = 1;
+ (*num)++;
+ mutex_unlock (&dyn_lock);
+ return 0;
+ }
+ else if ((*vec)[i] == el)
+ {
+ (*aux_vec)[i].refs++;
+ mutex_unlock (&dyn_lock);
+ return 0;
+ }
+
+ new_sz = *sz + 4;
+ new_vec = realloc (*vec, new_sz * sizeof (void *));
+ new_aux_vec = realloc (*aux_vec, new_sz * sizeof (struct aux));
+
+ if (!new_vec || !new_aux_vec)
+ {
+ if (free_el)
+ (*free_el) (el);
+ /* One of the vectors might be the wrong size, but who cares. */
+ return ENOMEM;
+ }
+
+ for (i = *sz; i < new_sz; i++)
+ new_vec[i] = 0;
+
+ new_vec[*sz] = el;
+ new_aux_vec[*sz].free_el = free_el;
+ new_aux_vec[*sz].refs = 1;
+ (*num)++;
+
+ *vec = new_vec;
+ *aux_vec = new_aux_vec;
+ *sz = new_sz;
+
+ mutex_unlock (&dyn_lock);
+
+ return 0;
+}
+
+/* Scan VEC_V, which should be a vector of SZ pointers of the same type as
+ EL, for EL; if it is found, then decrement its reference count, and if
+ that goes to zero, decrement *NUM and free EL if it had an associated free
+ routine passed to add_el. */
+static void
+drop_el (void *el, void *vec_v, struct aux *aux_vec,
+ size_t sz, size_t *num)
+{
+ int i;
+ void **vec;
+
+ if (! el)
+ return;
+
+ mutex_lock (&dyn_lock);
+
+ vec = vec_v;
+
+ for (i = 0; i < sz; i++)
+ if (vec[i] == el)
+ {
+ if (aux_vec[i].refs == 1)
+ {
+ if (aux_vec[i].free_el)
+ (*aux_vec[i].free_el) (el);
+ vec[i] = 0;
+ (*num)--;
+ }
+ else
+ aux_vec[i].refs--;
+ break;
+ }
+
+ mutex_unlock (&dyn_lock);
+}
+
+/* Add the port class *CLASS to the list of control port classes recognized
+ by trivfs; if *CLASS is 0, an attempt is made to allocate a new port
+ class, which is stored in *CLASS. */
+error_t
+trivfs_add_control_port_class (struct port_class **class)
+{
+ /* XXX Gee, there *is no* way of freeing port classes or buckets! So we
+ actually never free anything! */
+
+ if (! *class)
+ {
+ *class = ports_create_class (trivfs_clean_cntl, 0);
+ if (! *class)
+ return ENOMEM;
+ }
+
+ return
+ add_el (*class, 0,
+ &trivfs_dynamic_control_port_classes,
+ &dynamic_control_port_classes_aux,
+ &dynamic_control_port_classes_sz,
+ &trivfs_num_dynamic_control_port_classes);
+}
+
+/* Remove the previously added dynamic control port class CLASS, freeing it
+ if it was allocated by trivfs_add_control_port_class. */
+void
+trivfs_remove_control_port_class (struct port_class *class)
+{
+ drop_el (class,
+ trivfs_dynamic_control_port_classes,
+ dynamic_control_port_classes_aux,
+ dynamic_control_port_classes_sz,
+ &trivfs_num_dynamic_control_port_classes);
+}
+
+/* Add the port class *CLASS to the list of protid port classes recognized by
+ trivfs; if *CLASS is 0, an attempt is made to allocate a new port class,
+ which is stored in *CLASS. */
+error_t
+trivfs_add_protid_port_class (struct port_class **class)
+{
+ /* XXX Gee, there *is no* way of freeing port classes or buckets! So we
+ actually never free anything! */
+
+ if (! *class)
+ {
+ *class = ports_create_class (trivfs_clean_protid, 0);
+ if (! *class)
+ return ENOMEM;
+ }
+
+ return
+ add_el (*class, 0,
+ &trivfs_dynamic_protid_port_classes,
+ &dynamic_protid_port_classes_aux,
+ &dynamic_protid_port_classes_sz,
+ &trivfs_num_dynamic_protid_port_classes);
+}
+
+/* Remove the previously added dynamic protid port class CLASS, freeing it
+ if it was allocated by trivfs_add_protid_port_class. */
+void
+trivfs_remove_protid_port_class (struct port_class *class)
+{
+ drop_el (class,
+ trivfs_dynamic_protid_port_classes,
+ dynamic_protid_port_classes_aux,
+ dynamic_protid_port_classes_sz,
+ &trivfs_num_dynamic_protid_port_classes);
+}
+
+/* Add the port bucket *BUCKET to the list of dynamically allocated port
+ buckets; if *bucket is 0, an attempt is made to allocate a new port
+ bucket, which is then stored in *bucket. */
+error_t
+trivfs_add_port_bucket (struct port_bucket **bucket)
+{
+ /* XXX Gee, there *is no* way of freeing port bucketes or buckets! So we
+ actually never free anything! */
+
+ if (! *bucket)
+ {
+ *bucket = ports_create_bucket ();
+ if (! *bucket)
+ return ENOMEM;
+ }
+
+ return
+ add_el (*bucket, 0,
+ &trivfs_dynamic_port_buckets,
+ &dynamic_port_buckets_aux,
+ &dynamic_port_buckets_sz,
+ &trivfs_num_dynamic_port_buckets);
+}
+
+/* Remove the previously added dynamic port bucket BUCKET, freeing it
+ if it was allocated by trivfs_add_port_bucket. */
+void
+trivfs_remove_port_bucket (struct port_bucket *bucket)
+{
+ drop_el (bucket,
+ trivfs_dynamic_port_buckets,
+ dynamic_port_buckets_aux,
+ dynamic_port_buckets_sz,
+ &trivfs_num_dynamic_port_buckets);
+}
diff --git a/libtrivfs/protid-classes.c b/libtrivfs/protid-classes.c
new file mode 100644
index 00000000..a1ff3822
--- /dev/null
+++ b/libtrivfs/protid-classes.c
@@ -0,0 +1,22 @@
+/* Defaults for TRIVFS_PROTID_[N]PORTCLASSES
+
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "trivfs.h"
+
+struct port_class *trivfs_protid_portclasses[1] = { 0 };
+int trivfs_protid_nportclasses = 0;