[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH v2] libc: POSIX: Eine notduerftige sys/select.h



+ libc: POSIX: Ein select(), das fuer Lesen per fgetc()/ungetc()
  zusammengehackt ist, beim Schreiben immer ja und bei Fehlern immer
  nein sagt. Dazu ein fd_set als 32-Bit-Bitmaske und passende Makros.
---
 src/modules/include/sys/select.h |   74 ++++++++++++++++++++++
 src/modules/lib/posix/select.c   |  128 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 202 insertions(+), 0 deletions(-)
 create mode 100644 src/modules/include/sys/select.h
 create mode 100644 src/modules/lib/posix/select.c

diff --git a/src/modules/include/sys/select.h b/src/modules/include/sys/select.h
new file mode 100644
index 0000000..cc53b7d
--- /dev/null
+++ b/src/modules/include/sys/select.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2009 The tyndur Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the tyndur Project
+ * by Kevin Wolf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _SYS_SELECT_H_
+#define _SYS_SELECT_H_
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#ifndef CONFIG_LIBC_NO_STUBS
+
+/**
+ * Menge von Dateideskriptoren
+ *
+ * FIXME Irgendwann will man da sicher mehr als 32 benutzen koennen
+ */
+typedef struct {
+    uint32_t bits;
+} fd_set;
+
+#define FD_ZERO(fdset) do { (fdset).bits = 0; } while (0)
+#define FD_SET(fd, fdset) do { (fdset).bits |= (1 << (fd)); } while (0)
+#define FD_CLR(fd, fdset) do { (fdset).bits &= ~(1 << (fd)); } while (0)
+#define FD_ISSET(fd, fdset) ((fdset).bits & (1 << (fd)))
+
+/**
+ * Prueft, welche der gegebenen Dateideskriptoren bereit zum Lesen oder
+ * Schreiben sind oder ein Fehler fuer sie aufgetreten ist. Dateideskriptoren
+ * die nicht bereit bzw. in einem Fehlerzustand sind, werden aus der Menge
+ * entfernt.
+ *
+ * @param number_fds Nummer des hoechsten Dateideskriptors in einem der
+ * uebergebenen Mengen.
+ * @param readfds Dateideskriptoren, bei denen ueberprueft werden soll, ob sie
+ * zum Lesen bereit sind.
+ * @param writefds Dateideskriptoren, bei denen ueberprueft werden soll, ob sie
+ * zum Schreiben bereit sind.
+ * @param errfds Dateideskriptoren, bei denen ueberprueft werden soll, ob sie
+ * in einem Fehlerzustand sind.
+ * @param timeout Maximales Timeout, das gewartet werden soll, falls kein
+ * Deskriptor bereit ist. NULL fuer dauerhaftes Blockieren.
+ *
+ * @return Anzahl der Dateideskriptoren, die bereit bzw. in einem Fehlerzustand
+ * sind
+ */
+int select(int number_fds, fd_set* readfds, fd_set* writefds,
+    fd_set* errfds, struct timeval* timeout);
+#endif
+
+#endif
diff --git a/src/modules/lib/posix/select.c b/src/modules/lib/posix/select.c
new file mode 100644
index 0000000..539f555
--- /dev/null
+++ b/src/modules/lib/posix/select.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2009 The tyndur Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the tyndur Project
+ * by Kevin Wolf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/select.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <syscall.h>
+
+#ifndef CONFIG_LIBC_NO_STUBS
+/**
+ * Prueft, welche der gegebenen Dateideskriptoren bereit zum Lesen oder
+ * Schreiben sind oder ein Fehler fuer sie aufgetreten ist. Dateideskriptoren
+ * die nicht bereit bzw. in einem Fehlerzustand sind, werden aus der Menge
+ * entfernt.
+ *
+ * @param number_fds Nummer des hoechsten Dateideskriptors in einem der
+ * uebergebenen Mengen.
+ * @param readfds Dateideskriptoren, bei denen ueberprueft werden soll, ob sie
+ * zum Lesen bereit sind.
+ * @param writefds Dateideskriptoren, bei denen ueberprueft werden soll, ob sie
+ * zum Schreiben bereit sind.
+ * @param errfds Dateideskriptoren, bei denen ueberprueft werden soll, ob sie
+ * in einem Fehlerzustand sind.
+ * @param timeout Maximales Timeout, das gewartet werden soll, falls kein
+ * Deskriptor bereit ist. NULL fuer dauerhaftes Blockieren.
+ *
+ * @return Anzahl der Dateideskriptoren, die bereit bzw. in einem Fehlerzustand
+ * sind
+ */
+int select(int number_fds, fd_set* readfds, fd_set* writefds,
+    fd_set* errfds, struct timeval* timeout)
+{
+    uint32_t* rd = (uint32_t*) readfds;
+    uint32_t* wr = (uint32_t*) writefds;
+    uint32_t* err = (uint32_t*) errfds;
+    int c;
+    FILE* f;
+    int ret;
+
+    uint32_t orig_rd = rd ? *rd : 0;
+    uint32_t orig_wr = wr ? *wr : 0;
+
+    uint64_t timeout_tick;
+    if (timeout != NULL) {
+        timeout_tick = get_tick_count() + timeout->tv_sec +
+            1000ULL * 1000ULL * timeout->tv_usec;
+    } else {
+        timeout_tick = (uint64_t) -1;
+    }
+
+    // tyndur ist so toll, bei uns gibt es keine Fehler
+    if (err) {
+        *err = 0;
+    }
+
+    do {
+        int i;
+
+        // Wieder alles zuruecksetzen
+        ret = 0;
+        if (rd) {
+            *rd = orig_rd;
+        }
+        if (wr) {
+            *wr = orig_wr;
+        }
+
+
+        for (i = 0; i < 32; i++) {
+
+            // Versuchsweise ein Zeichen auslesen. Wenn das funktioniert, als
+            // lesbar werten und das Zeichen schnell wieder zurueckstecken
+            // bevor das Programm was merkt.
+            if (rd && (*rd & (1 << i))) {
+                f = fdopen(i, NULL);
+
+                if (f != NULL) {
+                    c = fgetc(f);
+                    if (c == 0 || c == EOF) {
+                        *rd &= ~(1 << i);
+                    } else {
+                        ungetc(c, f);
+                        ret++;
+                    }
+                }
+            }
+
+            // Schreiben geht immer
+            if (wr && (*wr & (1 << i))) {
+                ret++;
+            }
+        }
+
+        // Busy Wait waere irgendwie auch doof
+        if (ret == 0) {
+            yield();
+        }
+
+    } while ((ret == 0) && (timeout_tick > get_tick_count()));
+
+    return ret;
+}
+#endif
-- 
1.6.0.2