diff options
Diffstat (limited to 'libtrivfs')
-rw-r--r-- | libtrivfs/cntl-classes.c | 22 | ||||
-rw-r--r-- | libtrivfs/dyn-classes.c | 269 | ||||
-rw-r--r-- | libtrivfs/protid-classes.c | 22 |
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; |