aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxutil/kernel_stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libxutil/kernel_stream.c')
-rw-r--r--tools/libxutil/kernel_stream.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/tools/libxutil/kernel_stream.c b/tools/libxutil/kernel_stream.c
new file mode 100644
index 0000000000..345b048015
--- /dev/null
+++ b/tools/libxutil/kernel_stream.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/** @file
+ * An IOStream implementation using printk() for output.
+ * Input is not implemented.
+ */
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "kernel_stream.h"
+#include "allocate.h"
+
+/** Number of characters in the output buffer.
+ * The kernel uses 1024 for printk, so that should suffice.
+ */
+#define BUF_N 1024
+
+/** State for a kernel stream. */
+typedef struct KernelData {
+ /** Stream lock. We need a lock to serialize access to the stream. */
+ spinlock_t lock;
+ /** Saved flags for locking. */
+ unsigned long flags;
+ /** Size of the output buffer. */
+ int buf_n;
+ /** Output buffer. */
+ char buf[BUF_N];
+} KernelData;
+
+static int kernel_write(IOStream *s, const char *msg, int n);
+static void kernel_free(IOStream *s);
+static void kernel_stream_lock(IOStream *s);
+static void kernel_stream_unlock(IOStream *s);
+
+/** Methods for a kernel stream. Output only. */
+static const IOMethods kernel_methods = {
+ write: kernel_write,
+ free: kernel_free,
+ lock: kernel_stream_lock,
+ unlock: kernel_stream_unlock,
+};
+
+/** Shared state for kernel streams.
+ * All implementations write using printk, so we can use
+ * shared state and avoid allocating it.
+ */
+static const KernelData kernel_data = {
+ lock: SPIN_LOCK_UNLOCKED,
+ flags: 0,
+ buf_n: BUF_N,
+};
+
+/** Stream for kernel printk. */
+static IOStream iokernel = {
+ methods: &kernel_methods,
+ data: &kernel_data,
+};
+
+/** Stream for kernel printk. */
+IOStream *iostdout = &iokernel;
+
+/** Stream for kernel printk. */
+IOStream *iostdin = &iokernel;
+
+/** Stream for kernel printk. */
+IOStream *iostderr = &iokernel;
+
+/** Get an output-only stream implementation using
+ * printk(). The stream uses static storage, and must not be freed.
+ *
+ * @return kernel stream
+ */
+IOStream get_stream_kernel(void){
+ return iokernel;
+}
+
+/** Obtain the lock on the stream state.
+ *
+ * @param kdata stream state
+ */
+static inline void KernelData_lock(KernelData *kdata){
+ spin_lock_irqsave(&kdata->lock, kdata->flags);
+}
+
+/** Release the lock on the stream state.
+ *
+ * @param kdata stream state
+ */
+static inline void KernelData_unlock(KernelData *kdata){
+ spin_unlock_irqrestore(&kdata->lock, kdata->flags);
+}
+
+/** Get the stream state.
+ *
+ * @param s kernel stream
+ * @return stream state
+ */
+static inline KernelData *get_kernel_data(IOStream *s){
+ return (KernelData*)s->data;
+}
+
+/** Obtain the lock on the stream state.
+ *
+ * @param s stream
+ */
+void kernel_stream_lock(IOStream *s){
+ KernelData_lock(get_kernel_data(s));
+}
+
+/** Release the lock on the stream state.
+ *
+ * @param s stream
+ */
+void kernel_stream_unlock(IOStream *s){
+ KernelData_unlock(get_kernel_data(s));
+}
+
+/** Write to a kernel stream.
+ *
+ * @param stream kernel stream
+ * @param format print format
+ * @param args print arguments
+ * @return result of the print
+ */
+static int kernel_write(IOStream *stream, const char *buf, int n){
+ KernelData *kdata = get_kernel_data(stream);
+ int k;
+ k = kdata->buf_n - 1;
+ if(n < k) k = n;
+ memcpy(kdata->buf, buf, k);
+ kdata->buf[k] = '\0'
+ printk(kdata->buf);
+ return k;
+}
+
+/** Free a kernel stream.
+ * Frees the internal state of the stream.
+ * Do not call this unless the stream was dynamically allocated.
+ * Do not call this on a stream returned from get_stream_kernel().
+ *
+ * @param io stream to free
+ */
+static void kernel_free(IOStream *io){
+ KernelData *kdata;
+ if(io == &iokernel) return;
+ kdata = get_kernel_data(io);
+ zero(kdata, sizeof(*kdata));
+ deallocate(kdata);
+}
+#endif /* __KERNEL__ */
+
+
+
+