Various internal datastructures, and communication between source
files.

Signed-off-by: Tony Ibbs <t...@tonyibbs.co.uk>
---
 ipc/kbus_internal.h |  626 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 626 insertions(+), 0 deletions(-)
 create mode 100644 ipc/kbus_internal.h

diff --git a/ipc/kbus_internal.h b/ipc/kbus_internal.h
new file mode 100644
index 0000000..2d9e737
--- /dev/null
+++ b/ipc/kbus_internal.h
@@ -0,0 +1,626 @@
+/* KBUS kernel module - internal definitions
+ *
+ * This is a character device driver, providing the messaging support
+ * for KBUS.
+ *
+ * This header contains the definitions used internally by kbus.c.
+ * At the moment nothing else is expected to include this file.
+ *
+ * KBUS clients should include (at least) kbus_defns.h.
+ */
+
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the KBUS Lightweight Linux-kernel mediated
+ * message system
+ *
+ * The Initial Developer of the Original Code is Kynesim, Cambridge UK.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Kynesim, Cambridge UK
+ *   Tony Ibbs <t...@tonyibbs.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * GNU Public License version 2 (the "GPL"), in which case the provisions of
+ * the GPL are applicable instead of the above.  If you wish to allow the use
+ * of your version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL.  If you do not delete the
+ * provisions above, a recipient may use your version of this file under either
+ * the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#ifndef _kbus_internal
+#define _kbus_internal
+
+/*
+ * KBUS can support multiple devices, as /dev/kbus<N>. These all have
+ * the same major device number, and map to differing minor device
+ * numbers. <N> will also be the minor device number, but don't rely
+ * on that for anything.
+ *
+ * When KBUS starts up, it will always setup a single device (/dev/kbus0),
+ * but it can be asked to setup more - for instance:
+ *
+ *     # insmod kbus.ko kbus_num_devices=5
+ *
+ * There is also an IOCTL to allow user-space to request a new device as
+ * necessary. The hot plugging mechanisms should cause the device to appear "as
+ * if by magic".
+ *
+ *     (This last means that we *could* default to setting up zero devices
+ *     at module startup, and leave the user to ask for the first one, but
+ *     that seems rather cruel.)
+ *
+ * We need to set a maximum number of KBUS devices (corresponding to a limit on
+ * minor device numbers). The obvious limit (corresponding to what we'd have
+ * got if we used the deprecated "register_chrdev" to setup our device) is 256,
+ * so we'll go with that.
+ */
+#define KBUS_MIN_NUM_DEVICES             1
+
+#ifdef CONFIG_KBUS_MAX_NUM_DEVICES
+#define KBUS_MAX_NUM_DEVICES           CONFIG_KBUS_MAX_NUM_DEVICES
+#else
+#define KBUS_MAX_NUM_DEVICES           256
+#endif
+
+#ifndef CONFIG_KBUS_DEF_NUM_DEVICES
+#define CONFIG_KBUS_DEF_NUM_DEVICES    1
+#endif
+
+/*
+ * Our initial array sizes could arguably be made configurable
+ * for tuning, if we discover this is useful
+ */
+#define KBUS_INIT_MSG_ID_MEMSIZE       16
+#define KBUS_INIT_LISTENER_ARRAY_SIZE  8
+
+/*
+ * Setting CONFIG_KBUS_DEBUG will cause the Makefile
+ * to define DEBUG for us
+ */
+#ifdef DEBUG
+#define kbus_maybe_dbg(kbus_dev, format, args...) do { \
+       if ((kbus_dev)->verbose) \
+               (void) dev_dbg((kbus_dev)->dev, format, ## args); \
+} while (0)
+#else
+#define kbus_maybe_dbg(kbus_dev, format, args...) ((void)0)
+#endif
+
+/*
+ * This is really only directly useful if CONFIG_KBUS_DEBUG is on
+ */
+#ifdef CONFIG_KBUS_DEBUG_DEFAULT_VERBOSE
+#define KBUS_DEFAULT_VERBOSE_SETTING true
+#else
+#define KBUS_DEFAULT_VERBOSE_SETTING false
+#endif
+
+/* ========================================================================= */
+
+/* We need a way of remembering message bindings */
+struct kbus_message_binding {
+       struct list_head list;
+       struct kbus_private_data *bound_to;     /* who we're bound to */
+       u32 bound_to_id;        /* but the id is often useful */
+       u32 is_replier;         /* bound as a replier */
+       u32 name_len;
+       char *name;             /* the message name */
+};
+
+/*
+ * For both keeping track of requests sent (to which we still want replies)
+ * and replies read (to which we haven't yet sent a reply), we need some
+ * means of remembering message ids. Since I'd rather not worry the rest of
+ * the code with how this is implemented (which is code for "I'll implement
+ * it very simply and worry about making it efficient/scalable later"), and
+ * since we always want to remember both the message ids and also how many
+ * there are, it seems sensible to bundle this up in its own datastructure.
+ */
+struct kbus_msg_id_mem {
+       u32 count;      /* Number of entries in use */
+       u32 size;       /* Actual size of the array */
+       u32 max_count;  /* Max 'count' we've had */
+       /*
+        * An array is probably the worst way to store a list of message ids,
+        * but it's *very simple*, and should work OK for a smallish number of
+        * message ids. So it's a place to start...
+        *
+        * Note the array may have "unused" slots, signified by message id {0:0}
+        */
+       struct kbus_msg_id *ids;
+};
+
+/* An item in the list of requests that a Ksock has not yet replied to */
+struct kbus_unreplied_item {
+       struct list_head list;
+       struct kbus_msg_id id;  /* the request's id */
+       u32 from;               /* the sender's id */
+       struct kbus_name_ptr *name_ref; /* and its name... */
+       u32 name_len;
+};
+
+/*
+ * The parts of a message being written to KBUS (via kbus_write[_parts]),
+ * or read by the user (via kbus_read) are:
+ *
+ * * the user-space message header - as in 'struct kbus_message_header'
+ *
+ * from which we copy various items into our own internal message header.
+ *
+ * For a "pointy" message, that is all there is.
+ *
+ * For an "entire" message, this is then followed by:
+ *
+ * * the message name
+ * * padding to bring that up to a NULL terminator and then a 4-byte boundary.
+ *
+ * If the "entire" message has data, then this is followed by:
+ *
+ * * N data parts (all but the last of size PART_LEN)
+ * * padding to bring that up to a 4-byte boundary.
+ *
+ * and finally, whether there was data or not:
+ *
+ * * the final end guard.
+ *
+ * Remember that kbus_read always delivers an "entire" message.
+ */
+enum kbus_msg_parts {
+       KBUS_PART_HDR = 0,
+       KBUS_PART_NAME,
+       KBUS_PART_NPAD,
+       KBUS_PART_DATA,
+       KBUS_PART_DPAD,
+       KBUS_PART_FINAL_GUARD
+};
+/* N.B. New message parts require switch cases in kbus_msg_part_name()
+ * and kbus_write_parts().
+ */
+
+#define KBUS_NUM_PARTS (KBUS_PART_FINAL_GUARD+1)
+
+/*
+ * Replier typing.
+ * The higher the replier type, the more specific it is.
+ * We trust the binding mechanisms not to have created two replier
+ * bindings of the same type for the same name (so we shan't, for
+ * example, get '$.Fred.*' bound as replier twice).
+ */
+
+enum kbus_replier_type {
+       UNSET = 0,
+       WILD_STAR,
+       WILD_PERCENT,
+       SPECIFIC
+};
+
+/*
+ * A reference counting wrapper for message data
+ *
+ * If 'as_pages' is false, then the data is stored as a single kmalloc'd
+ * entity, pointed to by 'parts[0]'. In this case, 'num_parts' will be 1,
+ * and 'last_page_len' will be the size of the allocated data.
+ *
+ * If 'as_pages' is true, then the data is stored as 'num_parts' pages, each
+ * pointed to by 'parts[n]'. The last page should be treated as being size
+ * 'last_page_len' (even if the implementation is not enforcing this). All
+ * other pages are of size PART_LEN.
+ *
+ * In either case, 'lengths[n]' is a "fill counter" for how many bytes of data
+ * are actually being stored in page 'n'. Once the data is all in place, this
+ * should be equal to PART_LEN or 'last_page_len' as appropriate.
+ *
+ * 'refcount' is a stanard kernel reference count for the data - when it 
reaches
+ * 0, everything (the parts, the arrays and the datastructure) gets freed.
+ */
+struct kbus_data_ptr {
+       int as_pages;
+       unsigned num_parts;
+       unsigned long *parts;
+       unsigned *lengths;
+       unsigned last_page_len;
+       struct kref refcount;
+};
+
+/*
+ * A reference counting wrapper for message names
+ *
+ * RATIONALE:
+ *
+ * When a message name is copied from user space, we take our first copy.
+ *
+ * In order to send a message to a Ksock, we use kbus_push_message(), which
+ * takes a copy of the message for each recipient.
+ *
+ * We also take a copy of the message name for our list of messages that have
+ * been read but not replied to.
+ *
+ * It makes sense to copy the message header, because the contents thereof are
+ * changed according to the particular recipient.
+ *
+ * Copying the message data (if any) is handled by the kbus_data_ptr, above,
+ * which provides reference counting. This makes sense because message data may
+ * be large.
+ *
+ * If we only have one recipient, copying the message name is not a big issue,
+ * but if there are many, we would prefer not to make many copies of the
+ * string. It is, perhaps, worth keeping a dictionary of message names. and
+ * referring to the name in that - but that's not an incremental change from
+ * the "simple copying" state we start from.
+ *
+ * The simplest change to make, which may have some benefit, is to reference
+ * count the names for an individual message, as is done for the message data.
+ *
+ * If we have a single recipient, we will have copied the string from user
+ * space, and also created the kbus_name_ptr datastructure - an overhead of 8
+ * bytes. However, when we copy the message for the recipient, we do not need
+ * to copy the message name, so if the message name is more than 8 bytes, we
+ * have immediately made a gain (and experience shows that message names tend
+ * to be at least that long).
+ *
+ * As soon as we have more than one recipient, it becomes extremely likely that
+ * we have saved space, and we will definitely have saved allocations which
+ * could be fragmenting memory. So it sounds like a good thing to try.
+ *
+ * Also, if I later on want to store a hash code for the string (hoping to
+ * speed up comparisons), the new datastructure gives me somewhere to put it...
+ */
+struct kbus_name_ptr {
+       char *name;
+       struct kref refcount;
+};
+
+/*
+ * When the user reads a message from us, they receive a kbus_entire_message
+ * structure.
+ *
+ * When the user writes a message to us, they write a "pointy" message, using
+ * the kbus_message_header structure, or an "entire" message, using the
+ * kbus_entire_message structure.
+ *
+ * Within the kernel, all messages are held as "pointy" messages, but instead
+ * of direct pointers to the message name and data, we use reference counted
+ * pointers.
+ *
+ * Rather than overload the 'name' and 'data' pointer fields, with all the
+ * danger of getting it wrong that that implies, it seems simpler to have our
+ * own, internal to the kernel, clone of the datastructure, but with these
+ * fields defined correctly...
+ *
+ * Hmm. If we have the name and data references, perhaps we should move the
+ * name and data *lengths* into those same.
+ */
+
+struct kbus_msg {
+       struct kbus_msg_id id;  /* Unique to this message */
+       struct kbus_msg_id in_reply_to; /* Which message this is a reply to */
+       u32 to;         /* 0 (empty) or a replier id */
+       u32 from;       /* 0 (KBUS) or the sender's id */
+       struct kbus_orig_from orig_from;        /* Cross-network linkage */
+       struct kbus_orig_from final_to; /* Cross-network linkage */
+       u32 extra;      /* ignored field - future proofing */
+       u32 flags;      /* Message type/flags */
+       u32 name_len;   /* Message name's length, in bytes */
+       u32 data_len;   /* Message length, also in bytes */
+       struct kbus_name_ptr *name_ref;
+       struct kbus_data_ptr *data_ref;
+};
+
+/*
+ * The current message that the user is reading (with kbus_read())
+ *
+ * If 'msg' is NULL, then the data structure is "empty" (i.e., there is no
+ * message being read).
+ */
+struct kbus_read_msg {
+       struct kbus_entire_message user_hdr;    /* the header for user space */
+
+       struct kbus_msg *msg;   /* the internal message */
+       char *parts[KBUS_NUM_PARTS];
+       unsigned lengths[KBUS_NUM_PARTS];
+       int which;              /* The current item */
+       u32 pos;                /* How far they've read in it */
+       /*
+        * If the current item is KBUS_PART_DATA then we 'ref_data_index' is
+        * which part of the data we're in, and 'pos' is how far we are through
+        * that particular item.
+        */
+       u32 ref_data_index;
+};
+
+/*
+ * See kbus_write_parts() for how this data structure is actually used.
+ *
+ * If 'msg' is NULL, then the data structure is "empty" (i.e., there is no
+ * message being written).
+ *
+ * * 'is_finished' is true when we've got all the bytes for our message,
+ *   and thus don't want any more. It's an error for the user to try to
+ *   write more message after it is finished.
+ *
+ *   For a "pointy" message, this is set immediately after the message header
+ *   end guard is finished (the message name and any data aren't "pulled in"
+ *   until the user does SEND). For an "entire" message, this is set after the
+ *   final end guard is finished (so we will have the message name and any data
+ *   in memory).
+ *
+ * * 'pointers_are_local' is true if the message's name and data have been
+ *   transferred to kernel space (as reference counted entities), and false
+ *   if they are (still) in user space.
+ *
+ * * 'hdr' is the message header, the shorter in-kernel version.
+ *
+ * * 'which' indicates which part of the message we think we're being given
+ *   bytes for, from KBUS_PART_HDR through to (for an "entire" message)
+ *   KBUS_PART_FINAL_GUARD.
+ * * 'pos' is the index of the next byte within the current part of whatever
+ *   we're working on, as indicated by 'which'. Note that for message data,
+ *   this is the index within the whole of the data (not the index within a
+ *   data part).
+ *
+ * * If we're reading an "entire" message, then the message name gets written
+ *   to 'ref_name', which is a reference-counted string. This is allocated to
+ *   the correct size/shape for the entire message name, after the head has
+ *   been read.
+ *
+ *   The intention is that, if 'ref_name' is non-NULL, it should be legal
+ *   to call 'kbus_lower_name_ref()' on it, to free its contents.
+ *
+ * * Similarly, 'ref_data' is reference-counted data, again allocated to the
+ *   correct size/shape for the entire message data length, after the header
+ *   has been read. The 'length' for each part is used to indicate how far
+ *   through that part we have populated with bytes.
+ *
+ *   The intention is that, if 'ref_data' is non-NULL, it should be legal
+ *   to call 'kbus_lower_data_ref()' on it, to free its contents.
+ *
+ *  'ref_data_index' is then the index (starting at 0) of the referenced
+ *   data part that we are populating.
+ */
+struct kbus_write_msg {
+       struct kbus_entire_message user_msg;    /* from user space */
+       struct kbus_msg *msg;   /* our version of it */
+
+       u32 is_finished;
+       u32 pointers_are_local;
+       u32 guard;              /* Whichever guard we're reading */
+       char *user_name_ptr;    /* User space name */
+       void *user_data_ptr;    /* User space data */
+       enum kbus_msg_parts which;
+       u32 pos;
+       struct kbus_name_ptr *ref_name;
+       struct kbus_data_ptr *ref_data;
+       u32 ref_data_index;
+};
+
+/*
+ * This is the data for an individual Ksock
+ *
+ * Each time we open /dev/kbus<n>, we need to remember a unique id for
+ * our file-instance. Using 'filp' might work, but it's not something
+ * we have control over, and in particular, if the file is closed and
+ * then reopened, there's no guarantee that a particular value of 'filp'
+ * won't be used again. A simple serial number is safer.
+ *
+ * Each such "opening" also has a message queue associated with it. Any
+ * messages this "opening" has declared itself a listener (or replier)
+ * for will be added to that queue.
+ *
+ * 'id' is the unique id for this file descriptor - it enables stateful message
+ * transtions, etc. It is local to the particular KBUS device.
+ *
+ * 'last_msg_id_sent' is the message id of the last message that was
+ * (successfully) written to this file descriptor. It is needed when
+ * constructing a reply.
+ *
+ * We have a queue of messages waiting for us to read them, in 'message_queue'.
+ * 'message_count' is how many messages are in the queue, and 'max_messages'
+ * is an indication of how many messages we shall allow in the queue.
+ *
+ * Note that, however a message was originally sent to us, messages held
+ * internally are always a message header plus pointers to a message name and
+ * (optionally) message data. See kbus_send() for details.
+ */
+struct kbus_private_data {
+       struct list_head list;
+       struct kbus_dev *dev;   /* Which device we are on */
+       u32 id;         /* Our own id */
+       struct kbus_msg_id last_msg_id_sent;    /* As it says - see above */
+       u32 message_count;      /* How many messages for us */
+       u32 max_messages;       /* How many messages allowed */
+       struct list_head message_queue; /* Messages for us */
+
+       /*
+        * It's useful (for /proc/kbus/bindings) to remember the PID of the
+        * current process
+        */
+       pid_t pid;
+
+       /* Wait for something to appear in the message_queue */
+       wait_queue_head_t read_wait;
+
+       /* The message currently being read by the user */
+       struct kbus_read_msg read;
+
+       /* The message currently being written by the user */
+       struct kbus_write_msg write;
+
+       /* Are we currently sending that message? */
+       int sending;
+
+       /*
+        * Each request we send should (eventually) generate us a reply, or
+        * at worst a status message from KBUS itself telling us there isn't
+        * going to be one. So we need to ensure that there is room in our
+        * (as the sender) message queue to receive all/any such.
+        *
+        * Note that this *also* allows SEND to forbid sending a Reply to a
+        * Request that we did not receive (or to which we have already
+        * replied)
+        */
+       struct kbus_msg_id_mem outstanding_requests;
+
+       /*
+        * If we are a replier for a message, then KBUS wants to ensure
+        * that a reply is *definitely* made. If we release ourselves, then
+        * we're clearly not going to reply to any requests that we have
+        * read but not replied to, and KBUS would like to generate a status
+        * message for each such. So we need a list of the information needed
+        * to form such Status/Reply messages.
+        *
+        *     (Thus we don't need the whole of the original message, since
+        *     we're only *really* needing its name, its id and who its
+        *     from -- given which its easiest just to keep the parts we
+        *     *do* need, and ignore the data.)
+        *
+        * It was decided not to place a limit on the size of this list.
+        * Its size is limited by the ability of sender(s) to send
+        * requests, which in turn is limited by the the number of slots
+        * they can reserve for the replies to those requests in their
+        * own message queues.
+        *
+        * If a limit was imposed, then we would also need to stop a sender
+        * sending a request because the replier has too many replies
+        * outstanding (for instance, because it has gone to sleep). But
+        * then we'd assume that it is not responding to messages in
+        * general, and so its message queue would fill up, and that
+        * should be sufficient protection.
+        */
+       struct list_head replies_unsent;
+       u32 num_replies_unsent;
+       u32 max_replies_unsent;
+
+       /*
+        * Managing which messages a replier may reply to
+        * ----------------------------------------------
+        * We need to police replying, such that a replier may only reply
+        * to requests that it has received (where "received" means "had
+        * placed into its message queue", because KBUS must reply for us
+        * if the particular Ksock is not going to).
+        *
+        * It is possible to do this using either the 'outstanding_requests'
+        * or the 'replies_unsent' list.
+        *
+        * Using the 'outstanding_requests' list means that when a replier
+        * wants to send a reply, it needs to look up who the original-sender
+        * is (from its Ksock id, in the "from" field of the message), and
+        * check against that. This is a bit inefficient.
+        *
+        * Using the 'replies_unsent' list means that when a replier wants
+        * to send a reply, it just needs to find the right message stub
+        * in said 'replies_unsent' list, and check that the reply *does*
+        * match the original request. This may be more efficient, depending.
+        *
+        * In fact, the 'outstanding_requests' list is used, simply because
+        * it was implemented first.
+        */
+};
+
+/* What is a sensible number for the default maximum number of messages? */
+#ifndef CONFIG_KBUS_DEF_MAX_MESSAGES
+#define CONFIG_KBUS_DEF_MAX_MESSAGES   100
+#endif
+
+/* Information belonging to each /dev/kbus<N> device */
+struct kbus_dev {
+       struct cdev cdev;       /* Character device data */
+       struct device *dev;     /* Our very selves */
+
+       u32 index;              /* Which /dev/kbus<n> device we are */
+
+       /*
+        * The Big Lock
+        * We use a single mutex for all purposes, and all locking is done
+        * at the "top level", i.e., in the externally called functions.
+        * This simplifies the design of the internal (list processing,
+        * etc.) functions, at the possible cost of making interaction
+        * with KBUS, in general, slower.
+        *
+        * On the other hand, we favour reliable over fast.
+        */
+       struct mutex mux;
+
+       /* Who has bound to receive which messages in what manner */
+       struct list_head bound_message_list;
+
+       /*
+        * The actual Ksock entries (one per 'open("/dev/kbus<n>")')
+        * This is to allow us to find the 'kbus_private_data' instances,
+        * so that we can get at all the message queues. The details of
+        * how we do this are *definitely* going to change...
+        */
+       struct list_head open_ksock_list;
+
+       /* Has one of our Ksocks made space available in its message queue? */
+       wait_queue_head_t write_wait;
+
+       /*
+        * Each open file descriptor needs an internal id - this is used
+        * when binding messages to listeners, but is also needed when we
+        * want to reply. We reserve the id 0 as a special value ("none").
+        */
+       u32 next_ksock_id;
+
+       /*
+        * Every message sent has a unique id (again, unique per device).
+        */
+       u32 next_msg_serial_num;
+
+       /* Are we wanting debugging messages? */
+       u32 verbose;
+};
+
+/*
+ * Each entry in a message queue holds a single message, and a pointer to
+ * the message name binding that caused it to be added to the list. This
+ * makes it simple to remove messages from the queue if the message name
+ * binding is unbound. The binding shall be NULL for:
+ *
+ *  * Replies
+ *  * KBUS "synthetic" messages, which are also (essentialy) Replies
+ */
+struct kbus_message_queue_item {
+       struct list_head list;
+       struct kbus_msg *msg;
+       struct kbus_message_binding *binding;
+};
+
+/* The sizes of the parts in our reference counted data */
+#define KBUS_PART_LEN          PAGE_SIZE
+#define KBUS_PAGE_THRESHOLD    (PAGE_SIZE >> 1)
+
+/* Manage the files used to report KBUS internal state */
+/* From kbus_internal.c */
+#ifndef CONFIG_PROC_FS
+void kbus_setup_reporting(void) {}
+void kbus_remove_reporting(void) {}
+#else
+extern void kbus_setup_reporting(void);
+extern void kbus_remove_reporting(void);
+#endif
+/* From kbus.c itself */
+extern void kbus_get_device_data(int *num_devices,
+                                struct kbus_dev ***devices);
+extern u32 kbus_lenleft(struct kbus_private_data *priv);
+
+#endif /* _kbus_internal */
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-embedded" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to