summaryrefslogtreecommitdiff
path: root/libchannel/hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'libchannel/hub.c')
-rw-r--r--libchannel/hub.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/libchannel/hub.c b/libchannel/hub.c
new file mode 100644
index 000000000..31ee4d4b8
--- /dev/null
+++ b/libchannel/hub.c
@@ -0,0 +1,103 @@
+/* Generic channel hub functions.
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+ Written by Carl Fredrik Hammar <hammy.lite@gmail.com>
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd 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.
+
+ The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include <malloc.h>
+
+#include "channel.h"
+
+/* Allocate a new hub of CLASS with FLAGS set, then return it in HUB.
+ Return ENOMEM if memory for the hub couldn't be allocated. */
+error_t
+channel_alloc_hub (const struct channel_class *class, int flags,
+ struct channel_hub **hub)
+{
+ struct channel_hub *new_hub = malloc (sizeof (struct channel_hub));
+ if (! new_hub)
+ return ENOMEM;
+
+ new_hub->class = class;
+ new_hub->flags = flags;
+ new_hub->hook = 0;
+
+ *hub = new_hub;
+ return 0;
+}
+
+/* If not null call method clear_hub to deallocate class-specific bits of
+ HUB, then (regardless) free any generic resources used by it and
+ itself. */
+void
+channel_free_hub (struct channel_hub *hub)
+{
+ if (hub->class->clear_hub)
+ (*hub->class->clear_hub) (hub);
+
+ free (hub);
+}
+
+/* Set the flags FLAGS in HUB. Remove any already set flags in FLAGS, if
+ FLAGS then contain backend flags call set_hub_flags method with with
+ FLAGS or if set_hub_flags is null return EINVAL. Lastly generic flags
+ get set. */
+error_t
+channel_set_hub_flags (struct channel_hub *hub, int flags)
+{
+ int orig = hub->flags, new = flags & ~orig;
+ error_t err = 0;
+
+ if (new & CHANNEL_BACKEND_FLAGS)
+ {
+ if (hub->class->set_hub_flags)
+ err = (*hub->class->set_hub_flags) (hub, new);
+ else
+ err = EINVAL;
+ }
+
+ if (! err)
+ hub->flags |= (new & ~CHANNEL_BACKEND_FLAGS);
+
+ return err;
+}
+
+/* Clear the flags FLAGS in HUB. Remove any already cleared flags in
+ FLAGS, if FLAGS then contain backend flags call clear_hub_flags method
+ with with FLAGS or if clear_hub_flags is null return EINVAL. Lastly
+ generic flags get clear. */
+error_t
+channel_clear_hub_flags (struct channel_hub *hub, int flags)
+{
+ int orig = hub->flags, kill = flags & orig;
+ error_t err = 0;
+
+ if (kill & CHANNEL_BACKEND_FLAGS)
+ {
+ if (hub->class->clear_hub_flags)
+ err = (*hub->class->clear_hub_flags) (hub, kill);
+ else
+ err = EINVAL;
+ }
+
+ if (! err)
+ hub->flags &= ~(kill & ~CHANNEL_BACKEND_FLAGS);
+
+ return err;
+}