summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Fredrik Hammar <hammy.lite@gmail.com>2007-08-16 12:08:53 +0000
committerThomas Schwinge <tschwinge@gnu.org>2009-10-06 09:51:34 +0200
commit7c89b863b5c510b04a366c10a5c7342906c86daf (patch)
treeadeee4fe7a2f02cc80cf598848d7db627671d8ea
parentf1a4d6327f269e5b6fc8cbca87c1f0c3b3bfb4b7 (diff)
2007-08-16 Carl Fredrik Hammar <hammy.lite@gmail.com>
* tests/test-1.c (triv_fifo_open): New function. (triv_fifo_cleanup): Rename to triv_fifo_close. (triv_fifo_create): Remove. (triv_fifo_create_hub) New function. (triv_fifo_read): Use class_hook instead of hook. (triv_fifo_write): Likewise. (main): Create triv_fifo hub. (main): Open triv_fifo channel. (main): Close triv_fifo channel. (triv_fifo_class): Set name. (triv_fifo_class): Set open and close methods. * Makefile (SRCS): Add hub.c * hub.c: New file. * channel.c (channel_create): Rename to channel_alloc. (channel_alloc): Remove class parameter. (channel_alloc): Add hub parameter. (channel_alloc): Use class_hook instead of hook. (channel_free): Don't call cleanup method. (channel_open): New function. (channel_close): New function. (channel_set_flags): Get class through hub. (channel_clear_flags): Likewise. (channel_read): Likewise. (channel_write): Likewise. * channel.h: Merge channel and channel_class page. : Merge channel function pages into single page. (struct channel): Remove field class. (struct channel): New field hub. (struct channel): Rename hook to class_hook. (struct channel_hub): New struct. (struct channel_class): Rename method cleanup to close. (struct channel_class): Fix close comment. (struct channel_class): New methods open, close, set_hub_flags, clear_hub_flags, clear_hub. (channel_create): Rename to channel_alloc. (channel_alloc): Remove class parameter. (channel_alloc): Add hub parameter. (channel_free): Fix comment. (channel_open, channel_close): New functions. (channel_alloc_hub, channel_free_hub): New functions. (channel_set_hub_flags, channel_clear_hub_flags): Likewise.
-rw-r--r--libchannel/ChangeLog49
-rw-r--r--libchannel/Makefile2
-rw-r--r--libchannel/channel.c61
-rw-r--r--libchannel/channel.h108
-rw-r--r--libchannel/hub.c103
-rw-r--r--libchannel/tests/test-1.c68
6 files changed, 313 insertions, 78 deletions
diff --git a/libchannel/ChangeLog b/libchannel/ChangeLog
index c84c8092d..859853823 100644
--- a/libchannel/ChangeLog
+++ b/libchannel/ChangeLog
@@ -1,3 +1,51 @@
+2007-08-16 Carl Fredrik Hammar <hammy.lite@gmail.com>
+
+ * tests/test-1.c (triv_fifo_open): New function.
+ (triv_fifo_cleanup): Rename to triv_fifo_close.
+ (triv_fifo_create): Remove.
+ (triv_fifo_create_hub) New function.
+ (triv_fifo_read): Use class_hook instead of hook.
+ (triv_fifo_write): Likewise.
+ (main): Create triv_fifo hub.
+ (main): Open triv_fifo channel.
+ (main): Close triv_fifo channel.
+ (triv_fifo_class): Set name.
+ (triv_fifo_class): Set open and close methods.
+
+ * Makefile (SRCS): Add hub.c
+
+ * hub.c: New file.
+
+ * channel.c (channel_create): Rename to channel_alloc.
+ (channel_alloc): Remove class parameter.
+ (channel_alloc): Add hub parameter.
+ (channel_alloc): Use class_hook instead of hook.
+ (channel_free): Don't call cleanup method.
+ (channel_open): New function.
+ (channel_close): New function.
+ (channel_set_flags): Get class through hub.
+ (channel_clear_flags): Likewise.
+ (channel_read): Likewise.
+ (channel_write): Likewise.
+
+ * channel.h: Merge channel and channel_class page.
+ : Merge channel function pages into single page.
+ (struct channel): Remove field class.
+ (struct channel): New field hub.
+ (struct channel): Rename hook to class_hook.
+ (struct channel_hub): New struct.
+ (struct channel_class): Rename method cleanup to close.
+ (struct channel_class): Fix close comment.
+ (struct channel_class): New methods open, close, set_hub_flags,
+ clear_hub_flags, clear_hub.
+ (channel_create): Rename to channel_alloc.
+ (channel_alloc): Remove class parameter.
+ (channel_alloc): Add hub parameter.
+ (channel_free): Fix comment.
+ (channel_open, channel_close): New functions.
+ (channel_alloc_hub, channel_free_hub): New functions.
+ (channel_set_hub_flags, channel_clear_hub_flags): Likewise.
+
2007-08-07 Carl Fredrik Hammar <hammy.lite@gmail.com>
* channel.c (channel_create): Initialize hook.
@@ -5,6 +53,7 @@
* channel.h (channel_create): Fix comment.
+
2007-07-18 Carl Fredrik Hammar <hammy.lite@gmail.com>
* channel.c (channel_create channel_free): Improve comments.
diff --git a/libchannel/Makefile b/libchannel/Makefile
index a24a78641..57df3dec8 100644
--- a/libchannel/Makefile
+++ b/libchannel/Makefile
@@ -26,7 +26,7 @@ makemode := library
libname := libchannel
installhdrs := channel.h
-SRCS = channel.c
+SRCS = channel.c hub.c
LCLHDRS := channel.h
OBJS = $(SRCS:.c=.o)
diff --git a/libchannel/channel.c b/libchannel/channel.c
index 517884a04..abddf2be0 100644
--- a/libchannel/channel.c
+++ b/libchannel/channel.c
@@ -1,4 +1,4 @@
-/* Channel I/O
+/* Generic channel functions.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2007
Free Software Foundation, Inc.
@@ -26,38 +26,59 @@
#include "channel.h"
-/* Allocate a new channel of class CLASS, with FLAGS set and return it
- in CHANNEL. Return ENOMEM if memory for channel couldn't be
- allocated. */
+/* Allocate a new channel of hub HUB, with FLAGS set, then return it in
+ CHANNEL. Return ENOMEM if memory for the hub couldn't be allocated. */
error_t
-channel_create (const struct channel_class *class,
- int flags, struct channel **channel)
+channel_alloc (struct channel_hub *hub, int flags,
+ struct channel **channel)
{
struct channel *new = malloc (sizeof (struct channel));
if (!new)
return ENOMEM;
new->flags = flags;
- new->class = class;
- new->hook = 0;
+ new->hub = hub;
+ new->class_hook = 0;
*channel = new;
return 0;
}
-/* If not null call method cleanup to deallocate class-specific bits of
- CHANNEL, then free it (regardless) and any generic resources used by
- it. */
+/* Free CHANNEL and any generic resources allocated for it. */
void
channel_free (struct channel *channel)
{
- if (channel->class->cleanup)
- (*channel->class->cleanup) (channel);
-
free (channel);
}
+/* Allocate a new channel, open it, and return it in CHANNEL. Uses
+ HUB's open method and passes FLAGS to it, unless it's null. */
+error_t
+channel_open (struct channel_hub *hub, int flags,
+ struct channel **channel)
+{
+ error_t err = channel_alloc (hub, flags, channel);
+ if (err)
+ return err;
+
+ if (hub->class->open)
+ err = (*hub->class->open) (*channel, flags);
+
+ return err;
+}
+
+/* Call CHANNEL's close method, unless it's null, then free it
+ (regardless.) */
+void
+channel_close (struct channel *channel)
+{
+ if (channel->hub->class->close)
+ (*channel->hub->class->close) (channel);
+
+ channel_free (channel);
+}
+
/* Set the flags FLAGS in CHANNEL. Remove any already set flags in FLAGS,
if FLAGS contain any backend flags call set_flags method or if
set_flags is null return EINVAL. Lastly generic flags get set. */
@@ -69,8 +90,8 @@ channel_set_flags (struct channel *channel, int flags)
if (new & CHANNEL_BACKEND_FLAGS)
{
- if (channel->class->set_flags)
- err = (*channel->class->set_flags) (channel, new);
+ if (channel->hub->class->set_flags)
+ err = (*channel->hub->class->set_flags) (channel, new);
else
err = EINVAL;
}
@@ -93,8 +114,8 @@ channel_clear_flags (struct channel *channel, int flags)
if (kill & CHANNEL_BACKEND_FLAGS)
{
- if (channel->class->clear_flags)
- err = (*channel->class->clear_flags) (channel, kill);
+ if (channel->hub->class->clear_flags)
+ err = (*channel->hub->class->clear_flags) (channel, kill);
else
err = EINVAL;
}
@@ -116,7 +137,7 @@ channel_read (struct channel *channel, size_t amount,
if (channel->flags & CHANNEL_WRITEONLY)
return EPERM;
- return (*channel->class->read) (channel, amount, buf, len);
+ return (*channel->hub->class->read) (channel, amount, buf, len);
}
/* Write LEN bytes of BUF to CHANNEL, AMOUNT is set to the amount actually
@@ -129,5 +150,5 @@ channel_write (struct channel *channel, const void *buf,
if (channel->flags & CHANNEL_READONLY)
return EPERM;
- return (*channel->class->write) (channel, buf, len, amount);
+ return (*channel->hub->class->write) (channel, buf, len, amount);
}
diff --git a/libchannel/channel.h b/libchannel/channel.h
index de01f2ca3..922ce99e4 100644
--- a/libchannel/channel.h
+++ b/libchannel/channel.h
@@ -31,29 +31,22 @@
struct channel
{
int flags;
- const struct channel_class *class;
- void *hook;
+ struct channel_hub *hub;
+ void *class_hook;
};
-
-/* Flags implemented by generic channel code. */
-#define CHANNEL_READONLY 0x1 /* No writing allowed. */
-#define CHANNEL_WRITEONLY 0x2 /* No reading allowed. */
-#define CHANNEL_GENERIC_FLAGS (CHANNEL_READONLY | CHANNEL_WRITEONLY)
-/* Flags implemented by each backend. */
-#define CHANNEL_HARD_READONLY 0x010 /* Can't be made writable. */
-#define CHANNEL_HARD_WRITEONLY 0x020 /* Can't be made readable. */
+struct channel_hub
+{
+ int flags;
+ const struct channel_class *class;
+ void *hook; /* For class use. */
+};
-#define CHANNEL_BACKEND_SPEC_BASE 0x100 /* Here up are backend-specific */
-#define CHANNEL_BACKEND_FLAGS (CHANNEL_HARD_READONLY \
- | CHANNEL_HARD_WRITEONLY
- | ~(CHANNEL_BACKEND_SPEC_BASE - 1))
-
struct channel_class
{
/* Name of the class. */
const char *name;
-
+
/* Read at most AMOUNT bytes from CHANNEL into BUF and LEN with the
usual return buf semantics. Blocks until data is available or return
0 bytes on EOF. May not be null. See channel_read. */
@@ -74,22 +67,57 @@ struct channel_class
be null. See channel_clear_flags. */
error_t (*clear_flags) (struct channel *channel, int flags);
- /* Free any class-specific resources allocated for CHANNEL. May be
- null. */
- void (*cleanup) (struct channel *channel);
+ /* Open CHANNEL and set FLAGS. May be null. See channel_open. */
+ error_t (*open) (struct channel *channel, int flags);
+
+ /* Free any resources allocated for CHANNEL. May be null. See
+ channel_close. */
+ void (*close) (struct channel *channel);
+
+ /* Set any backend handled flags in HUB specified in FLAGS. May be
+ null. See channel_set_hub_flags. */
+ error_t (*set_hub_flags) (struct channel_hub *hub, int flags);
+
+ /* Clear any backend handled flags in HUB specified in FLAGS. May be
+ null. See channel_clear_hub_flags. */
+ error_t (*clear_hub_flags) (struct channel_hub *hub, int flags);
+
+ /* Free any class-specific resources allocated for HUB. May be null.
+ See channel_free_hub. */
+ void (*clear_hub) (struct channel_hub *hub);
};
-/* Allocate a new channel of class CLASS, with FLAGS set and return it
- in CHANNEL. Return ENOMEM if memory for channel couldn't be
- allocated. */
-error_t channel_create (const struct channel_class *class,
- int flags, struct channel **channel);
-
-/* If not null call method cleanup to deallocate class-specific bits of
- CHANNEL, then free it (regardless) and any generic resources used by
- it. */
+/* Flags implemented by generic channel code. */
+#define CHANNEL_READONLY 0x1 /* No writing allowed. */
+#define CHANNEL_WRITEONLY 0x2 /* No reading allowed. */
+#define CHANNEL_GENERIC_FLAGS (CHANNEL_READONLY | CHANNEL_WRITEONLY)
+
+/* Flags implemented by each backend. */
+#define CHANNEL_HARD_READONLY 0x010 /* Can't be made writable. */
+#define CHANNEL_HARD_WRITEONLY 0x020 /* Can't be made readable. */
+
+#define CHANNEL_BACKEND_SPEC_BASE 0x100 /* Here up are backend-specific */
+#define CHANNEL_BACKEND_FLAGS (CHANNEL_HARD_READONLY \
+ | CHANNEL_HARD_WRITEONLY \
+ | ~(CHANNEL_BACKEND_SPEC_BASE - 1))
+
+/* Allocate a new channel of hub HUB, with FLAGS set, then return it in
+ CHANNEL. Return ENOMEM if memory for the hub couldn't be allocated. */
+error_t channel_alloc (struct channel_hub *hub, int flags,
+ struct channel **channel);
+
+/* Free CHANNEL and any generic resources allocated for it. */
void channel_free (struct channel *channel);
+/* Allocate a new channel, open it, and return it in CHANNEL. Uses
+ HUB's open method and passes FLAGS to it, unless it's null. */
+error_t channel_open (struct channel_hub *hub, int flags,
+ struct channel **channel);
+
+/* Call CHANNEL's close method, unless it's null, then free it
+ (regardless.) */
+void channel_close (struct channel *channel);
+
/* Set the flags FLAGS in CHANNEL. Remove any already set flags in FLAGS,
if FLAGS contain any backend flags call set_flags method or if
set_flags is null return EINVAL. Lastly generic flags get set. */
@@ -100,7 +128,7 @@ error_t channel_set_flags (struct channel *channel, int flags);
clear_flags is null return EINVAL. Lastly generic flags get
cleared. */
error_t channel_clear_flags (struct channel *channel, int flags);
-
+
/* Reads at most AMOUNT bytes from CHANNEL into BUF and LEN with the usual
return buf semantics. Block until data is available and return 0 bytes
on EOF. If channel is write-only return EPERM, otherwise forward call
@@ -113,5 +141,27 @@ error_t channel_read (struct channel *channel, size_t amount,
return EPERM, otherwise forward call to CHANNEL's write method. */
error_t channel_write (struct channel *channel, const void *buf,
size_t len, size_t *amount);
+
+/* 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);
+
+/* 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);
+
+/* 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);
+
+/* 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);
#endif /* __CHANNEL_H__ */
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;
+}
diff --git a/libchannel/tests/test-1.c b/libchannel/tests/test-1.c
index 70fab36cf..9ab2b332f 100644
--- a/libchannel/tests/test-1.c
+++ b/libchannel/tests/test-1.c
@@ -56,7 +56,7 @@ triv_fifo_read (struct channel *channel,
mach_msg_type_number_t amount,
void **buf, mach_msg_type_number_t *len)
{
- struct buf *fifo_buf = channel->hook;
+ struct buf *fifo_buf = channel->class_hook;
int n = MIN (amount, fifo_buf->len);
size_t new_len = fifo_buf->len - n;
int alloced = 0;
@@ -90,7 +90,7 @@ triv_fifo_write (struct channel *channel,
const void *buf, mach_msg_type_number_t len,
mach_msg_type_number_t *amount)
{
- struct buf *fifo_buf = channel->hook;
+ struct buf *fifo_buf = channel->class_hook;
size_t old_len = fifo_buf->len;
size_t new_len = old_len + len;
error_t err;
@@ -105,39 +105,43 @@ triv_fifo_write (struct channel *channel,
return 0;
}
+static error_t
+triv_fifo_open (struct channel *channel, int flags)
+{
+ struct buf *buf;
+
+ buf = malloc (sizeof (struct buf));
+ if (! buf)
+ return ENOMEM;
+
+ buf->len = 0;
+
+ channel->class_hook = buf;
+ return 0;
+}
+
static void
-triv_fifo_cleanup (struct channel *fifo)
+triv_fifo_close (struct channel *fifo)
{
- free (fifo->hook);
+ free (fifo->class_hook);
}
const struct channel_class triv_fifo_class =
{
- "", triv_fifo_read, triv_fifo_write, 0, 0, triv_fifo_cleanup
-};
+ .name = "triv_fifo",
-error_t
-triv_fifo_create (int flags, struct channel **channel)
-{
- error_t err;
- struct buf *buf;
+ .open = triv_fifo_open,
+ .close = triv_fifo_close,
- err = channel_create (&triv_fifo_class, flags | CHANNEL_INNOCUOUS,
- channel);
- if (err)
- return err;
-
- buf = malloc (sizeof (struct buf));
- if (!buf)
- {
- channel_free (*channel);
- return ENOMEM;
- }
+ .read = triv_fifo_read,
+ .write = triv_fifo_write
+};
- buf->len = 0;
- (*channel)->hook = buf;
- return 0;
+error_t
+triv_fifo_create_hub (int flags, struct channel_hub **hub)
+{
+ return channel_alloc_hub (&triv_fifo_class, flags, hub);
}
static error_t
@@ -184,6 +188,7 @@ do_writes (struct channel *fifo, void *buf, size_t len, size_t step)
int
main (int argc, char **argv)
{
+ struct channel_hub *fifo_hub;
struct channel *fifo;
void *data, *buf;
size_t len = 128 * 1024;
@@ -194,9 +199,13 @@ main (int argc, char **argv)
if (data == MAP_FAILED)
error (1, errno, "main");
- err = triv_fifo_create (0, &fifo);
+ err = triv_fifo_create_hub (0, &fifo_hub);
if (err)
- error (1, err, "triv_fifo_create");
+ error (1, err, "triv_fifo_create_hub");
+
+ err = channel_open (fifo_hub, 0, &fifo);
+ if (err)
+ error (1, err, "triv_fifo_open");
/* Fill test data. */
for (i = 0; i < len; i++)
@@ -228,6 +237,9 @@ main (int argc, char **argv)
if (memcmp (data, buf, len) != 0)
error (1, 0, "written data inconsistent with read data");
-
+
+ channel_close (fifo);
+ channel_free_hub (fifo_hub);
+
return 0;
}