More junkcode!
authorRusty Russell <rusty@rustcorp.com.au>
Thu, 2 Jul 2009 03:32:39 +0000 (13:02 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 2 Jul 2009 03:32:39 +0000 (13:02 +0930)
junkcode/fork0@users.sf.net-bitmaps/bitmaps.h [new file with mode: 0644]
junkcode/fork0@users.sf.net-timeout/timeout.c [new file with mode: 0644]

diff --git a/junkcode/fork0@users.sf.net-bitmaps/bitmaps.h b/junkcode/fork0@users.sf.net-bitmaps/bitmaps.h
new file mode 100644 (file)
index 0000000..05ecd96
--- /dev/null
@@ -0,0 +1,78 @@
+/* bitmaps and bitmap operations */
+#ifndef _BITMAPS_H_
+#define _BITMAPS_H_
+
+/*
+ * Bitmaps are arrays of unsigned ints, filled with bits in most-
+ * significant-first order. So bitmap[0] shall contain the bits from
+ * 0 to 31 on a 32bit architecture, bitmap[1] - 32-63, and so forth.
+ *
+ * The callers are responsible to do all the bounds-checking.
+ */
+enum { BITS_PER_BITMAP_ELEM = 8 * sizeof(unsigned) };
+
+typedef unsigned bitmap_elem_t;
+
+/* returned is the unshifted bit state. IOW: NOT 0 or 1, but something
+ * like 0x00001000 or 0x40000000 */
+static inline
+bitmap_elem_t bitmap_test_bit(const bitmap_elem_t* bits, unsigned bit)
+{
+    if ( sizeof(*bits) == 4 )
+       return bits[bit >> 5] & (0x80000000 >> (bit & 0x1f));
+    else if ( sizeof(*bits) == 8 )
+       return bits[bit >> 6] & (0x8000000000000000ull >> (bit & 0x3f));
+    else
+    {
+       return bits[bit / BITS_PER_BITMAP_ELEM] &
+           1 << ((BITS_PER_BITMAP_ELEM - bit % BITS_PER_BITMAP_ELEM) - 1);
+    }
+}
+
+static inline
+bitmap_elem_t bitmap_set_bit(bitmap_elem_t* bits, unsigned bit)
+{
+    if ( sizeof(*bits) == 4 )
+       return bits[bit >> 5] |= (0x80000000 >> (bit & 0x1f));
+    else if ( sizeof(*bits) == 8 )
+       return bits[bit >> 6] |= (0x8000000000000000ull >> (bit & 0x3f));
+    else
+    {
+       return bits[bit / BITS_PER_BITMAP_ELEM] |=
+           1 << ((BITS_PER_BITMAP_ELEM - bit % BITS_PER_BITMAP_ELEM) - 1);
+    }
+}
+
+/* pos must position the bits inside of a bitmap element, otherwise
+ * the index shift puts the bits in the wrong word (for simplicity).
+ * Only low 8 bits of b8 shall be used */
+static inline
+void bitmap_set_8bits_fast(bitmap_elem_t* bits, unsigned pos, unsigned b8)
+{
+    if ( sizeof(*bits) == 4 )
+       bits[pos >> 5] |= b8 << (24 - (pos & 0x1f));
+    else if ( sizeof(*bits) == 8 )
+       bits[pos >> 6] |= b8 << (56 - (pos & 0x3f));
+    else
+    {
+       bits[pos / BITS_PER_BITMAP_ELEM] |=
+           b8 << (BITS_PER_BITMAP_ELEM - 8 - pos % BITS_PER_BITMAP_ELEM);
+    }
+}
+
+static inline
+bitmap_elem_t bitmap_clear_bit(bitmap_elem_t* bits, unsigned bit)
+{
+    if ( sizeof(*bits) == 4 )
+       return bits[bit >> 5] &= ~(0x80000000 >> (bit & 0x1f));
+    else if ( sizeof(*bits) == 8 )
+       return bits[bit >> 6] &= ~(0x8000000000000000ull >> (bit & 0x3f));
+    else
+    {
+       return bits[bit / BITS_PER_BITMAP_ELEM] &=
+           ~(1 << ((BITS_PER_BITMAP_ELEM - bit % BITS_PER_BITMAP_ELEM) - 1));
+    }
+}
+
+#endif /* _BITMAPS_H_ */
+
diff --git a/junkcode/fork0@users.sf.net-timeout/timeout.c b/junkcode/fork0@users.sf.net-timeout/timeout.c
new file mode 100644 (file)
index 0000000..290e427
--- /dev/null
@@ -0,0 +1,173 @@
+/* execute a program with a timeout by alarm(2) */
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+static const char *argv0;
+static char **prgargv;
+static pid_t pid;
+static int signo;
+static unsigned int timeout;
+
+static void timedout(int sig)
+{
+       fprintf(stderr, "%s[%d]: %s[%d] timed out after %u sec\n",
+               argv0, getpid(), *prgargv, pid, timeout);
+       if (pid)
+               kill(-pid, signo);
+}
+
+static void interrupted(int sig)
+{
+       alarm(0);
+       if (pid)
+               kill(-pid, sig);
+}
+
+static void usage()
+{
+       fprintf(stderr, "%s <timeout-seconds> [-<signal>] program ...\n"
+               "Where <signal> is a signal number (see kill -l).\n"
+               "Some symbolic names recognized. KILL used by default\n",
+               argv0);
+       exit(1);
+}
+
+static struct {
+       const char *name;
+       int signo;
+} known[] = {
+       {"HUP",     SIGHUP},
+       {"INT",     SIGINT},
+       {"QUIT",    SIGQUIT},
+       {"ILL",     SIGILL},
+       {"TRAP",    SIGTRAP},
+       {"ABRT",    SIGABRT},
+       {"BUS",     SIGBUS},
+       {"FPE",     SIGFPE},
+       {"KILL",    SIGKILL},
+       {"USR1",    SIGUSR1},
+       {"SEGV",    SIGSEGV},
+       {"USR2",    SIGUSR2},
+       {"PIPE",    SIGPIPE},
+       {"ALRM",    SIGALRM},
+       {"TERM",    SIGTERM},
+       {"STKFLT",  SIGSTKFLT},
+       {"CHLD",    SIGCHLD},
+       {"CONT",    SIGCONT},
+       {"STOP",    SIGSTOP},
+       {"TSTP",    SIGTSTP},
+       {"TTIN",    SIGTTIN},
+       {"TTOU",    SIGTTOU},
+       {"URG",     SIGURG},
+       {"XCPU",    SIGXCPU},
+       {"XFSZ",    SIGXFSZ},
+       {"VTALRM",  SIGVTALRM},
+       {"PROF",    SIGPROF},
+       {"WINCH",   SIGWINCH},
+       {"IO",      SIGIO},
+       {"PWR",     SIGPWR},
+       {"SYS",     SIGSYS},
+};
+
+static int signo_arg(const char *arg)
+{
+       if (*arg == '-') {
+               char *p;
+               int s = strtol(++arg, &p, 10);
+               if (!*p && p > arg && s > 0 && s < _NSIG) {
+                       signo = s;
+                       return 1;
+               }
+               if (!strncasecmp(arg, "SIG", 3))
+                       arg += 3;
+               for (s = 0; s < sizeof(known)/sizeof(*known); ++s)
+                       if (!strcasecmp(arg, known[s].name)) {
+                               signo = known[s].signo;
+                               return 1;
+                       }
+       }
+       return 0;
+}
+
+int main(int argc, char** argv)
+{
+       argv0 = strrchr(*argv, '/');
+       if (argv0)
+               ++argv0;
+       else
+               argv0 = *argv;
+
+       signal(SIGALRM, timedout);
+       signal(SIGINT, interrupted);
+       signal(SIGHUP, interrupted);
+
+       ++argv;
+
+       if (!*argv)
+               usage();
+
+       if (signo_arg(*argv))
+               ++argv;
+       if (sscanf(*argv, "%u", &timeout) == 1)
+               ++argv;
+       else
+               usage();
+       if (!signo && signo_arg(*argv))
+               ++argv;
+       if (!signo)
+               signo = SIGKILL;
+
+       if (!*argv)
+               usage();
+
+       prgargv = argv;
+       alarm(timeout);
+       pid = fork();
+
+       if (!pid) {
+               signal(SIGALRM, SIG_DFL);
+               signal(SIGCHLD, SIG_DFL);
+               signal(SIGINT, SIG_DFL);
+               signal(SIGHUP, SIG_DFL);
+               setpgid(0, 0);
+               execvp(*prgargv, prgargv);
+               fprintf(stderr, "%s: %s: %s\n",
+                       argv0, *prgargv, strerror(errno));
+               _exit(2);
+       } else if (pid < 0) {
+               fprintf(stderr, "%s: %s\n", argv0, strerror(errno));
+       } else {
+               int status;
+               while (waitpid(pid, &status, 0) < 0 && EINTR == errno)
+                       ;
+               alarm(0);
+               if (WIFEXITED(status))
+                       return WEXITSTATUS(status);
+               if (WIFSIGNALED(status)) {
+                       /*
+                        * Some signals are special, lets die with
+                        * the same signal as child process
+                        */
+                       if (WTERMSIG(status) == SIGHUP  ||
+                           WTERMSIG(status) == SIGINT  ||
+                           WTERMSIG(status) == SIGTERM ||
+                           WTERMSIG(status) == SIGQUIT ||
+                           WTERMSIG(status) == SIGKILL) {
+                               signal(WTERMSIG(status), SIG_DFL);
+                               raise(WTERMSIG(status));
+                       }
+                       fprintf(stderr, "%s: %s: %s\n",
+                               argv0, *prgargv, strsignal(WTERMSIG(status)));
+               }
+               else
+                       fprintf(stderr, "%s died\n", *prgargv);
+       }
+       return 2;
+}