a first pass at cleaning up the configure stuff new cothread library started, some...
authorAndy Wingo <wingo@pobox.com>
Sun, 27 Jan 2002 20:03:54 +0000 (20:03 +0000)
committerAndy Wingo <wingo@pobox.com>
Sun, 27 Jan 2002 20:03:54 +0000 (20:03 +0000)
Original commit message from CVS:
* a first pass at cleaning up the configure stuff
* new cothread library started, some experimental stack allocation code is in place

gst/cothreads/acconfig.h
gst/cothreads/acinclude.m4
gst/cothreads/configure.ac
gst/cothreads/cothread-stack.c [new file with mode: 0644]
gst/cothreads/linuxthreads-internals.h
gst/cothreads/pth.h.in
gst/cothreads/pth_p.h.in
gst/cothreads/test-pth-pthreads2.c

index e4d793b..61cad07 100644 (file)
@@ -54,6 +54,8 @@
 #undef PTH_DMALLOC
 #undef PTH_NEED_SEPARATE_REGISTER_STACK
 
+#undef HAVE_LINUXTHREADS
+
 @BOTTOM@
 
 #endif /* _PTH_ACDEF_H_ */
index b326db7..f54cb34 100644 (file)
@@ -1764,3 +1764,18 @@ AC_MSG_VERBOSE([$]$2)
 AC_MSG_VERBOSE([$]$3)
 ])
 
+dnl Check for LinuxThreads
+dnl COTHREADS_CHECK_LINUXTHREADS
+dnl no arguments
+AC_DEFUN([COTHREADS_CHECK_LINUXTHREADS], [
+       AC_CACHE_CHECK([for LinuxThreads],
+               [cothreads_cv_linuxthreads],
+               [AC_EGREP_CPP(pthread_kill_other_threads_np,
+                       [#include <pthread.h>],
+                       [cothreads_cv_linuxthreads=yes],
+                       [cothreads_cv_linuxthreads=no])
+               ])
+       if test $cothreads_cv_linuxthreads = yes; then
+               AC_DEFINE(HAVE_LINUXTHREADS,1,[if you have LinuxThreads])
+       fi
+])
index 33b5783..7cc6c27 100644 (file)
@@ -93,157 +93,28 @@ AC_MSG_PART(Mandatory Platform Environment)
 
 dnl # check for standard headers
 AC_HEADER_STDC
+# FIXME
 AC_HAVE_HEADERS(dnl
    stdio.h stdlib.h stdarg.h string.h signal.h unistd.h setjmp.h fcntl.h dnl
-   errno.h sys/types.h sys/time.h sys/wait.h sys/socket.h sys/socketcall.h)
+   errno.h sys/types.h)
 AC_CHECK_FUNCTIONS(dnl
-   gettimeofday select sigaction sigprocmask sigpending sigsuspend)
+   sigaction sigprocmask sigpending sigsuspend)
 AC_BEGIN_DECISION([mandatory system headers and functions])
 AC_IFALLYES(dnl
    header:stdio.h header:stdlib.h header:stdarg.h header:string.h dnl
    header:signal.h header:unistd.h header:setjmp.h header:fcntl.h header:errno.h dnl
-   header:sys/types.h header:sys/time.h header:sys/wait.h header:sys/socket.h dnl
-   func:gettimeofday func:select func:sigaction func:sigprocmask dnl
+   header:sys/types.h dnl
+   func:sigaction func:sigprocmask dnl
    func:sigpending func:sigsuspend,
    AC_DECIDE(fine, [all fine]))
 AC_END_DECISION
 
 AC_MSG_PART(Optional Platform Environment)
 
-dnl #  check for the number of signals
-dnl AC_CHECK_NSIG(PTH_NSIG)
-
-dnl # check whether poll(2)'s input stuff has to be faked
-AC_CHECK_FUNCTIONS(poll)
-AC_CHECK_DEFINE(POLLIN, poll.h)
-AC_MSG_CHECKING(whether poll(2) facility has to be faked)
-AC_IFALLYES(func:poll define:POLLIN, PTH_FAKE_POLL=0, PTH_FAKE_POLL=1)
-if test .$PTH_FAKE_POLL = .1; then
-    msg="yes"
-else
-    msg="no"
-fi
-AC_SUBST(PTH_FAKE_POLL)
-AC_MSG_RESULT([$msg])
-
-dnl # check for readv/writev environment
-AC_HAVE_HEADERS(sys/uio.h)
-AC_CHECK_FUNCTIONS(readv writev)
-AC_MSG_CHECKING(whether readv(2)/writev(2) facility has to be faked)
-AC_IFALLYES(func:readv func:writev header:sys/uio.h, PTH_FAKE_RWV=0, PTH_FAKE_RWV=1)
-if test .$PTH_FAKE_RWV = .1; then
-    msg="yes"
-else
-    msg="no"
-fi
-AC_SUBST(PTH_FAKE_RWV)
-AC_MSG_RESULT([$msg])
-
-dnl # check for various other functions which would be nice to have
-AC_CHECK_FUNCTIONS(usleep strerror)
-
-dnl # check for various other headers which we might need
-AC_HAVE_HEADERS(sys/resource.h net/errno.h)
-
-dnl # check whether we've to use a non-standard #include <sys/select.h>  to get
-dnl # the definition for fd_set under AIX and other brain-dead platforms.
-AC_HAVE_HEADERS(sys/select.h)
-EXTRA_INCLUDE_SYS_SELECT_H="#include <sys/select.h>"
-if test ".$ac_cv_header_sys_select_h" != .yes; then
-    EXTRA_INCLUDE_SYS_SELECT_H="/* $EXTRA_INCLUDE_SYS_SELECT_H */"
-fi
-AC_SUBST(EXTRA_INCLUDE_SYS_SELECT_H)
-
-dnl # check whether we've to define sig_atomic_t
-AC_CHECK_TYPEDEF(sig_atomic_t, signal.h)
-FALLBACK_SIG_ATOMIC_T="typedef int sig_atomic_t;"
-if test ".$ac_cv_typedef_sig_atomic_t" = .yes; then
-    FALLBACK_SIG_ATOMIC_T="/* $FALLBACK_SIG_ATOMIC_T */"
-fi
-AC_SUBST(FALLBACK_SIG_ATOMIC_T)
-
-dnl # check whether we've to define pid_t
-AC_CHECK_TYPEDEF(pid_t, sys/types.h)
-FALLBACK_PID_T="typedef int pid_t;"
-if test ".$ac_cv_typedef_pid_t" = .yes; then
-    FALLBACK_PID_T="/* $FALLBACK_PID_T */"
-fi
-AC_SUBST(FALLBACK_PID_T)
-
-dnl # check whether we've to define size_t
-AC_CHECK_TYPEDEF(size_t, stdlib.h)
-FALLBACK_SIZE_T="typedef unsigned int size_t;"
-if test ".$ac_cv_typedef_size_t" = .yes; then
-    FALLBACK_SIZE_T="/* $FALLBACK_SIZE_T */"
-fi
-AC_SUBST(FALLBACK_SIZE_T)
-
-dnl # check whether we've to define ssize_t
-AC_CHECK_TYPEDEF(ssize_t, sys/types.h)
-FALLBACK_SSIZE_T="typedef unsigned int ssize_t;"
-if test ".$ac_cv_typedef_ssize_t" = .yes; then
-    FALLBACK_SSIZE_T="/* $FALLBACK_SSIZE_T */"
-fi
-AC_SUBST(FALLBACK_SSIZE_T)
-
-dnl # check whether we've to define off_t
-AC_CHECK_TYPEDEF(off_t, sys/types.h)
-FALLBACK_OFF_T="typedef int off_t;"
-if test ".$ac_cv_typedef_off_t" = .yes; then
-    FALLBACK_OFF_T="/* $FALLBACK_OFF_T */"
-fi
-AC_SUBST(FALLBACK_OFF_T)
-
-dnl # check whether stack_t exists instead of sigaltstack
-AC_CHECK_TYPEDEF(stack_t, signal.h)
-
 dnl # check whether ss_base instead of ss_sp attribute exists
 AC_CHECK_STRUCTATTR(ss_base, sigaltstack, sys/signal.h)
 AC_CHECK_STRUCTATTR(ss_sp,   sigaltstack, sys/signal.h)
 
-dnl # check for gettimeofday() variant
-AC_MSG_CHECKING(for a single-argument based gettimeofday)
-cross_compile=no
-AC_TRY_COMPILE([
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-],[
-struct timeval tv;
-(void)gettimeofday(&tv);
-],
-msg="yes"
-,
-msg="no"
-)
-case $PLATFORM in
-    *-*-mvs* )  msg="no" ;; # on OS/390 the compiler test doesn't work
-    *-*-aix4* ) msg="no" ;; # on AIX the compiler test doesn't work
-    *-*-isc* )  msg="no" ;; # on ISC the compiler test doesn't work
-esac
-if test ".$msg" = .yes; then
-    AC_DEFINE(HAVE_GETTIMEOFDAY_ARGS1)
-fi
-AC_MSG_RESULT([$msg])
-
-dnl # check for struct timespec
-AC_MSG_CHECKING(for struct timespec)
-cross_compile=no
-AC_TRY_COMPILE([
-#include <time.h>
-#include <sys/time.h>
-],[
-struct timespec ts;
-],
-msg="yes"
-,
-msg="no"
-)
-if test ".$msg" = .yes; then
-    AC_DEFINE(HAVE_STRUCT_TIMESPEC)
-fi
-AC_MSG_RESULT([$msg])
-
 dnl ##
 dnl ##  MACHINE CONTEXT IMPLEMENTATION
 dnl ##
@@ -406,4 +277,3 @@ Makefile
 pth.h
 pth_acmac.h
 )
-
diff --git a/gst/cothreads/cothread-stack.c b/gst/cothreads/cothread-stack.c
new file mode 100644 (file)
index 0000000..efe6a4d
--- /dev/null
@@ -0,0 +1,207 @@
+/* Pthread-friendly coroutines with pth
+ * Copyright (C) 2001 Andy Wingo <wingo@pobox.com>
+ *
+ * cothread-stack.c: various methods of allocating cothread stacks
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+/* chunks can contain 1 or more blocks, each block contains one cothread stack */
+
+enum cothread_attr_method 
+{
+  COTHREAD_ATTR_METHOD_MALLOC,        /* cothread stacks on the heap, one block per chunk */
+  COTHREAD_ATTR_METHOD_GTHREAD_STACK, /* cothread stacks within the current gthread's stack */
+  COTHREAD_ATTR_METHOD_LINUXTHREADS,  /* a hack that allows for linuxthreads compatibility */
+}
+
+struct cothread_attr {
+  enum cothread_attr_method method;
+  int chunk_size;
+  int blocks_per_chunk;
+}
+
+#ifdef HAVE_LINUXTHREADS
+static struct cothread_attr cothread_attr_default = 
+{
+  COTHREAD_ATTR_METHOD_LINUXTHREADS,  /* use the linuxthreads hack */
+  0x20000,                            /* 2 MB */
+  8                                   /* for a stack size of 256 KB */
+}
+#else
+static struct cothread_attr cothread_attr_default = 
+{
+  COTHREAD_ATTR_METHOD_GTHREAD_STACK, /* this is what the old cothreads code does */
+  0x10000,                            /* only 1 MB due the the FreeBSD defaults */
+  8                                   /* for a stack size of 128 KB */
+}
+#endif
+
+static struct cothread_attr *_attr = NULL; /* set in cothread_init() */
+
+enum cothread_block_state
+{
+  COTHREAD_BLOCK_STATE_UNUSED=0,
+  COTHREAD_BLOCK_STATE_IN_USE
+}
+
+struct cothread_chunk {
+  struct cothread_chunk *next;
+  enum cothread_block_state *block_states;
+  char *chunk;
+  int size;
+  int reserved_bottom;
+  gboolean needs_free;
+}
+
+/* size must be a power of two. */
+struct cothread_chunk*
+cothread_chunk_new (unsigned long size, gboolean allocate)
+{
+  struct cothread_chunk *ret;
+  char *sp = CURRENT_STACK_FRAME;
+  
+  ret = g_new0 (struct cothread_chunk, 1);
+  ret->block_states = g_new0 (enum cothread_block_state, _attr->blocks_per_chunk);
+  
+  if (allocate) {
+    if (!posix_memalign(&ret->chunk, size, size))
+      g_error ("memalign operation failed");
+  } else {
+    /* if we don't allocate the chunk, we must already be in it. */
+
+    ret->chunk = (unsigned long) sp &~ (size - 1);
+#if PTH_STACK_GROWTH > 0
+    ret->reserved_bottom = sp - ret->chunk;
+#else
+    ret->reserved_bottom = sp + size - ret->chunk;
+#endif
+  }
+  
+  ret->size = size;
+  ret->needs_free = allocate;
+  
+  return ret;
+}
+
+gboolean
+cothread_stack_alloc_on_heap (char **low, char **high)
+{
+  *low = g_malloc (_attr->chunk_size / _attr->blocks_per_chunk);
+  *high = *low + sizeof (*low);
+  return TRUE;
+}
+
+/**
+ * cothread_stack_alloc_chunked:
+ * @chunk: the chunk for the 
+ * Make a new cothread stack out of a chunk. Chunks are assumed to be aligned on
+ * boundaries of _attr->chunk_size.
+ *
+ * Returns: the new cothread context
+ */
+  /* we assume that the stack is aligned on _attr->chunk_size boundaries */
+static gboolean
+cothread_stack_alloc_chunked (struct cothread_chunk *chunk, char **low, char **high, 
+                              (struct cothread_chunk*)(*chunk_new)(struct cothread_chunk*))
+{
+  int block;
+  struct cothread_chunk *walk, *last;
+  
+  for (walk=chunk; walk; last=walk, walk=walk->next) {
+    if (chunk->block_states[0] == COTHREAD_BLOCK_STATE_UNUSED) {
+      chunk->block_states[0] = COTHREAD_BLOCK_STATE_IN_USE;
+#if PTH_STACK_GROWTH > 0
+      *low  = chunk->chunk + chunk->reserved_bottom;
+      *high = chunk->chunk + chunk->chunk_size / _attr->blocks_per_chunk;
+#else
+      *low  = chunk->chunk + chunk->size * (chunk->nblocks - 1) / chunk->nblocks;
+      *high = chunk->chunk + chunk->size - chunk->reserved_bottom;
+#endif
+      return TRUE;
+    }
+    
+    for (block = 1; block < _attr->blocks_per_chunk; block++) {
+      if (chunk->block_states[block] == COTHREAD_BLOCK_STATE_UNUSED) {
+#if PTH_STACK_GROWTH > 0
+        *low  = chunk->chunk + chunk->size * (chunk->nblocks - block - 1) / chunk->nblocks;
+#else
+        *low  = chunk->chunk + chunk->size * (block - 1) / chunk->nblocks;
+#endif
+        *high = *low + chunk->size / chunk->nblocks;
+        return TRUE;
+      }
+    }
+  }
+  
+  if (!chunk_new)
+    return FALSE;
+  else
+    return cothread_stack_alloc_chunked (chunk_new (last), low, high, NULL);
+}
+
+gboolean
+cothread_stack_alloc_on_gthread_stack (char **low, char **high)
+{
+  struct cothread_chunk *chunk = NULL;
+  static GStaticPrivate chunk_key = G_STATIC_PRIVATE_INIT;
+  
+  if (!(chunk = g_static_private_get(&chunk_key))) {
+    chunk = cothread_chunk_new (_attr->size, FALSE);
+    g_static_private_set (&chunk_key, chunk, cothread_chunk_free);
+  }
+  
+  return cothread_stack_alloc_chunked (chunk, low, high, NULL);
+}
+
+gboolean
+cothread_stack_alloc_linuxthreads (char **low, char **high)
+{
+  struct cothread_chunk *chunk = NULL;
+  static GStaticPrivate chunk_key = G_STATIC_PRIVATE_INIT;
+  
+  if (!(chunk = g_static_private_get(&chunk_key))) {
+    chunk = cothread_chunk_new (_attr->size, FALSE);
+    g_static_private_set (&chunk_key, chunk, cothread_chunk_free);
+  }
+  
+  return cothread_stack_alloc_chunked (chunk, low, high, cothread_chunk_new_linuxthreads);
+}
+
+struct cothread_chunk*
+cothread_chunk_new_linuxthreads (struct cothread_chunk* old)
+{
+  struct cothread_chunk *new;
+  void *pthread_descr;
+  
+  new = cothread_chunk_new (_attr->chunk_size, TRUE);
+  pthread_descr = __linuxthreads_self();
+#if PTH_STACK_GROWTH > 0
+  /* we don't really know pthread_descr's size in this case, but we can be
+   * conservative. it's normally 1K in the down-growing case, so we allocate 2K.
+   */
+  new->reserved_bottom = 2048;
+  memcpy(new->chunk, pthread_descr, 2048);
+#else
+  new->reserved_bottom = ((unsigned long) pthread_descr | (_attr->chunk_size - 1)) - (unsigned long) pthread_descr;
+  memcpy(new->chunk + new->size - new->reserved_bottom - 1, pthread_descr, new->reserved_bottom);
+#endif
+  
+  old->next = new;
+  return new;
+}
+
+    
index b1419a7..ccf07d7 100644 (file)
@@ -1,38 +1,5 @@
-/* LinuxThreads internal data structures */
-/* hacked for use with gstreamer by andy wingo <wingo@pobox.com> */
-
-#include <bits/local_lim.h> /* PTHREAD_THREADS_MAX */
-#include <sys/types.h>      /* _pthread_fastlock */
-
 #ifndef CURRENT_STACK_FRAME
 #define CURRENT_STACK_FRAME  ({ char __csf; &__csf; })
 #endif /* CURRENT_STACK_FRAME */
 
-#ifndef STACK_SIZE
-#define STACK_SIZE 0x200000 /* 2 M linuxthreads default stack size */
-#endif
-
-typedef void * pthread_descr;
-
-/* Global array of thread handles, used for validating a thread id
-   and retrieving the corresponding thread descriptor. Also used for
-   mapping the available stack segments. */
-
-#pragma weak __pthread_handles
-extern struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX];
-
-struct pthread_handle_struct {
-  struct _pthread_fastlock h_lock; /* Fast lock for sychronized access */
-  pthread_descr h_descr;        /* Thread descriptor or NULL if invalid */
-  char * h_bottom;              /* Lowest address in the stack thread */
-};
-
-typedef struct pthread_handle_struct * pthread_handle;
-
-/* Return the handle corresponding to a thread id */
-
-static inline pthread_handle thread_handle(pthread_t id)
-{
-  return &__pthread_handles[id % PTHREAD_THREADS_MAX];
-}
-
+#define STACK_SIZE 0x200000
index 2229d99..eaf7072 100644 (file)
@@ -43,7 +43,6 @@
     /* essential headers */
 #include <sys/types.h>     /* for ssize_t, off_t */
 #include <sys/signal.h>    /* for sigset_t       */
-@EXTRA_INCLUDE_SYS_SELECT_H@
 
     /* essential values */
 #ifndef FALSE
index 76a51e9..124a15b 100644 (file)
@@ -27,6 +27,9 @@
 #define _PTH_P_H_
 
 /* mandatory system headers */
+
+#include <errno.h>
+/*
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -35,7 +38,6 @@
 #include <signal.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <errno.h>
 #include <ctype.h>
 #include <time.h>
 #include <sys/types.h>
@@ -43,6 +45,7 @@
 #include <sys/wait.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
+*/
 
 /* library version */
 #define _PTH_VERS_C_AS_HEADER_
 #include "pth_acdef.h"
 #include "pth_acmac.h"
 
-/* optional system headers */
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-#ifdef HAVE_NET_ERRNO_H
-#include <net/errno.h>
-#endif
-
-/* dmalloc support */
-#ifdef PTH_DMALLOC
-#include <dmalloc.h>
-#endif
-
-/* paths */
-#ifdef HAVE_PATHS_H
-#include <paths.h>
-#endif
-#ifdef _PATH_BSHELL
-#define PTH_PATH_BINSH _PATH_BSHELL
-#else
-#define PTH_PATH_BINSH "/bin/sh"
-#endif
-
-/* non-blocking flags */
-#ifdef  O_NONBLOCK
-#define O_NONBLOCKING O_NONBLOCK
-#else
-#ifdef  O_NDELAY
-#define O_NONBLOCKING O_NDELAY
-#else
-#ifdef  FNDELAY
-#define O_NONBLOCKING FNDELAY
-#else
-#error "No O_NONBLOCK, O_NDELAY or FNDELAY flag available!"
-#endif
-#endif
-#endif
-
-/* compiler happyness: avoid ``empty compilation unit'' problem */
-#define COMPILER_HAPPYNESS(name) \
-    int __##name##_unit = 0;
-
 /* generated contents */
 BEGIN_DECLARATION
 ==#==
index ba55821..6a98303 100644 (file)
@@ -1,35 +1,7 @@
-#define __USE_GNU /* non-posix functions */
-#include <pthread.h>
-#undef __USE_GNU
 #include <stdio.h>
-#include "linuxthreads-internals.h"
+#include "linuxthreads.h"
 #include "pth_p.h"
 
-/* this function is only really necessary to get the main thread's
- * pthread_descr, as the other threads store the pthread_descr (actually the
- * first member of struct _pthread_descr_struct, which points to itself for the
- * default (non-indirected) case) at the top of the stack. */
-static _pthread_descr linuxthreads_self() 
-{
-  pthread_mutexattr_t mutexattr;
-  pthread_mutex_t mutex;
-  _pthread_descr self;
-  
-  pthread_mutexattr_init (&mutexattr);
-  pthread_mutexattr_setkind_np (&mutexattr, PTHREAD_MUTEX_ERRORCHECK_NP);
-  pthread_mutex_init (&mutex, &mutexattr);
-
-  pthread_mutex_lock (&mutex);
-  self = mutex.__m_owner;
-  pthread_mutex_unlock (&mutex);
-  
-  printf ("pthread_self: %d\n", pthread_self());
-  printf ("descr: %p\n", self);
-  printf ("*descr: %p\n", *(int*)self);
-  
-  return self;
-}
-
 pth_mctx_t main_context;
 int threadnum = 0;
 
@@ -49,7 +21,7 @@ void *pthread (void *unused)
   pth_mctx_t ctx;
   _pthread_descr descr;
   
-  descr = linuxthreads_self();
+  descr = __linuxthreads_self();
   printf ("sp: %p\n", sp);
   printf ("STACK_SIZE: %p\n", STACK_SIZE);
   printf ("sp | STACK_SIZE: 0x%x\n", (int) sp | STACK_SIZE );
@@ -84,7 +56,7 @@ int main (int argc, char *argv[])
   pthread_create (&tid, NULL, pthread, NULL);
   pthread_join (tid, NULL);
   
-  linuxthreads_self();
+  __linuxthreads_self();
   
   exit (0);
 }