diff options
author | Carl Fredrik Hammar <hammy.lite@gmail.com> | 2007-08-16 12:08:53 +0000 |
---|---|---|
committer | Thomas Schwinge <tschwinge@gnu.org> | 2009-10-06 09:51:34 +0200 |
commit | 7c89b863b5c510b04a366c10a5c7342906c86daf (patch) | |
tree | adeee4fe7a2f02cc80cf598848d7db627671d8ea | |
parent | f1a4d6327f269e5b6fc8cbca87c1f0c3b3bfb4b7 (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/ChangeLog | 49 | ||||
-rw-r--r-- | libchannel/Makefile | 2 | ||||
-rw-r--r-- | libchannel/channel.c | 61 | ||||
-rw-r--r-- | libchannel/channel.h | 108 | ||||
-rw-r--r-- | libchannel/hub.c | 103 | ||||
-rw-r--r-- | libchannel/tests/test-1.c | 68 |
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; } |