Index: /pjproject/trunk/README-configure
===================================================================
--- /pjproject/trunk/README-configure	(revision 433)
+++ /pjproject/trunk/README-configure	(revision 433)
@@ -0,0 +1,47 @@
+
+   Configuring the Build System
+   Update: 04 May 2006
+
+
+  1. Overview
+  
+  The "configure" script in pjproject root directory is not an autoconf script,
+but it's just a custom script to generate "build.mak" for the build system. 
+The "build.mak" file declares the following global Makefile variables:
+
+  MACHINE_NAME
+    The processor and hardware platform of the target. For each MACHINE_NAME,
+    there must be matching "m-*.mak" entry in "build/" subdirectory. For 
+    example, when MACHINE_NAME is declared as "i386", then there must be 
+    "m-i386.mak" file in "build/" subdirectory.
+  
+  OS_NAME
+    Operating system name, determines which "os-*.mak" in "build/" dir to use.
+
+  HOST_NAME
+     Build host name, determines which "host-*.mak" to use.
+
+  CC_NAME
+     Compiler name, determines which "cc-*.mak" to use.
+
+  TARGET_NAME
+     Determines suffix to be added to output files (for example,
+     "libpjsip-i386-linux-gcc.a"). The value normally is equal to
+     $(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME), but it can contain any value.
+  
+  CROSS_COMPILE
+     Determine the prefix to be applied when invoking build tools (for
+     example, "powerpc-rtems-"). The default is empty.
+
+
+  At present, the configure script CAN NOT be used for configuring cross
+compilation. For cross compiling, you must create the "build.mak" file
+manually.
+
+
+  2. Supported Hosts and Targets
+
+  The number of supported hosts and targets will (hopefully) increase over time.
+See "build/" subdirectory for list of supported machines, OSes, hosts, and
+compilers.
+
Index: project/trunk/build.mak.txt
===================================================================
--- /pjproject/trunk/build.mak.txt	(revision 432)
+++ 	(revision )
@@ -1,72 +1,0 @@
-#
-# This file contains all possible values for the build.mak. Select
-# the appropriate settings, and put it in build.mak.
-#
-# (Just in case "./configure" fails to detect the appropriate values).
-#
-# Build configurations:
-#
-# MACHINE_NAME values: 
-#	- i386 (generic x86)
-#	- sparc
-#	- alpha
-#
-# OS_NAME values:
-#	- win32 (generic windows)
-#	- linux
-#	- sunos
-#
-# CC_NAME values:
-#	- gcc
-#	- msvc
-#
-# HOST_NAME values:
-#	- win32 (Windows command line)
-#	- mingw (Windows, mingw)
-#	- unix
-#
-
-#
-# PalmOS 6 cross-compile, cygwin
-#
-#export MACHINE_NAME := m68k
-#export OS_NAME := palmos
-#export CC_NAME := gcc
-#export HOST_NAME := mingw
-
-#
-# Win32, mingw
-#
-#export MACHINE_NAME := i386
-#export OS_NAME := win32
-#export CC_NAME := gcc
-#export HOST_NAME := mingw
-
-#
-# Linux i386, gcc
-#
-export MACHINE_NAME := i386
-export OS_NAME := linux
-export CC_NAME := gcc
-export HOST_NAME := unix
-
-#
-# Linux KERNEL i386, gcc
-#
-#export MACHINE_NAME := i386
-#export OS_NAME := linux-kernel
-#export CC_NAME := gcc
-#export HOST_NAME := unix
-#export PJPROJECT_DIR := /usr/src/pjproject-0.3
-##export KERNEL_DIR = /usr/src/linux
-#export KERNEL_DIR = /usr/src/uml/linux
-#export KERNEL_ARCH = ARCH=um
-
-#
-# SunOS, sparc, gcc
-#
-#export MACHINE_NAME := sparc
-#export OS_NAME := sunos
-#export CC_NAME := gcc
-#export HOST_NAME := unix
-
Index: /pjproject/trunk/build/cc-gcc.mak
===================================================================
--- /pjproject/trunk/build/cc-gcc.mak	(revision 432)
+++ /pjproject/trunk/build/cc-gcc.mak	(revision 433)
@@ -1,4 +1,4 @@
 export CC = $(CROSS_COMPILE)gcc -c
-export AR = $(CROSS_COMPILE)ar r 
+export AR = $(CROSS_COMPILE)ar rv 
 export LD = $(CROSS_COMPILE)gcc
 export LDOUT = -o 
Index: /pjproject/trunk/build/host-unix.mak
===================================================================
--- /pjproject/trunk/build/host-unix.mak	(revision 432)
+++ /pjproject/trunk/build/host-unix.mak	(revision 433)
@@ -3,5 +3,5 @@
 export HOST_RMR := rm -rf @@
 export HOST_RMDIR := rm -rf @@
-export HOST_MKDIR := mkdir @@
+export HOST_MKDIR := mkdir -p @@
 export HOST_EXE := 
 export HOST_PSEP := /
Index: /pjproject/trunk/build/m-mpc860.mak
===================================================================
--- /pjproject/trunk/build/m-mpc860.mak	(revision 433)
+++ /pjproject/trunk/build/m-mpc860.mak	(revision 433)
@@ -0,0 +1,9 @@
+#
+# PowerPC MPC860 specific.
+# It's a PowerPC without floating point support.
+#
+export M_CFLAGS := $(CC_DEF)PJ_M_POWERPC=1 $(CC_DEF)PJ_HAS_FLOATING_POINT=0 -mcpu=860
+export M_CXXFLAGS :=
+export M_LDFLAGS := -mcpu=860
+export M_SOURCES :=
+
Index: /pjproject/trunk/build/os-rtems.mak
===================================================================
--- /pjproject/trunk/build/os-rtems.mak	(revision 433)
+++ /pjproject/trunk/build/os-rtems.mak	(revision 433)
@@ -0,0 +1,17 @@
+#
+# Global OS specific configurations for RTEMS OS.
+#
+# Thanks Zetron, Inc and Phil Torre <ptorre@zetron.com> for donating PJLIB
+# port to RTEMS.
+#
+export RTEMS_DEBUG := -ggdb3 -DRTEMS_DEBUG -DDEBUG -qrtems_debug 
+
+export OS_CFLAGS   := $(CC_DEF)PJ_RTEMS=1 \
+	-B$(RTEMS_LIBRARY_PATH)/lib/ -specs bsp_specs -qrtems
+
+export OS_CXXFLAGS := 
+
+export OS_LDFLAGS  := -B$(RTEMS_LIBRARY_PATH)/lib/ -specs bsp_specs -qrtems 
+
+export OS_SOURCES  := 
+
Index: /pjproject/trunk/build/rules.mak
===================================================================
--- /pjproject/trunk/build/rules.mak	(revision 432)
+++ /pjproject/trunk/build/rules.mak	(revision 433)
@@ -155,5 +155,5 @@
 	   if test -f $$F; then \
 	     echo "$(OBJDIR)/" | tr -d '\n' >> $(DEP_FILE); \
-	     if gcc -M $(DEPFLAGS) $$F | sed '/^#/d' >> $(DEP_FILE); then \
+	     if $(CC_NAME) -M $(DEPFLAGS) $$F | sed '/^#/d' >> $(DEP_FILE); then \
 		true; \
 	     else \
Index: /pjproject/trunk/configure
===================================================================
--- /pjproject/trunk/configure	(revision 432)
+++ /pjproject/trunk/configure	(revision 433)
@@ -2,12 +2,11 @@
 
 #
-# Detect machine
+# Detect machine, unless the choice has been made already.
 #
-MACHINE=`uname -p`
-if echo $MACHINE | grep unknown > /dev/null; then
-    MACHINE=`uname -m`
-fi;
+if [ "$MACHINE" = "" ]; then
+	MACHINE=`uname -m`
+fi	
 
-if echo $MACHINE | grep sparc > /dev/null; then
+if echo $MACHINE | grep sun4u > /dev/null; then
     MACHINE_NAME=sparc
 elif echo $MACHINE | grep i.86 > /dev/null; then
@@ -18,12 +17,15 @@
     MACHINE_NAME=powerpc
 else
-    echo "Unable to detect processor type ('uname -p' == '$MACHINE')"
+    echo "Unable to detect processor type ('uname -m' == '$MACHINE')"
     exit 1
 fi
 
 #
-# Detect OS and host
+# Detect OS and host, unless the choice has been made already
 #
-SYSTEM=`uname -s`
+if [ "$SYSTEM" = "" ]; then
+    SYSTEM=`uname -s`
+fi	
+ 
 
 if echo $SYSTEM | grep -i sunos > /dev/null; then
@@ -54,4 +56,7 @@
     OS_NAME=darwinos
     HOST_NAME=unix
+elif echo $SYSTEM | grep -i rtems > /dev/null; then
+    OS_NAME=rtems
+    HOST_NAME=unix
 else
     echo "Unable to detect system type ('uname -s' == '$SYSTEM')"
@@ -60,17 +65,22 @@
 
 #
-# Detect gcc
+# Detect gcc, unless it has been chosen already
 #
-if gcc --version 2>&1 > /dev/null; then
-    CC_NAME=gcc
-else
-    echo "Unable to find gcc"
-    exit 1
-fi
+if [ "$CC_NAME" = "" ]; then
+	if gcc --version 2>&1 > /dev/null; then
+		CC_NAME=gcc
+	else
+		echo "Unable to find gcc"
+		exit 1
+	fi
+fi	
+ 
 
 #
-# TARGET
+# Specify TARGET_NAME, if not already choosen.
 #
-TARGET_NAME=$MACHINE_NAME-$OS_NAME-$CC_NAME
+if [ "$TARGET_NAME" = "" ]; then
+   TARGET_NAME=$MACHINE_NAME-$OS_NAME-$CC_NAME
+fi
 
 
@@ -86,4 +96,5 @@
 echo " CC_NAME      = $CC_NAME"
 echo " TARGET_NAME  = $TARGET_NAME"
+echo " CROSS_COMPILE= $CROSS_COMPILE"
 echo " LINUX_POLL   = $LINUX_POLL"
 
@@ -94,4 +105,5 @@
 echo "export CC_NAME := $CC_NAME" >> build.mak
 echo "export TARGET_NAME := $TARGET_NAME" >> build.mak
+echo "export CROSS_COMPILE := $CROSS_COMPILE" >> build.mak
 echo "export LINUX_POLL := $LINUX_POLL" >> build.mak
 
Index: /pjproject/trunk/pjlib/build/os-rtems.mak
===================================================================
--- /pjproject/trunk/pjlib/build/os-rtems.mak	(revision 433)
+++ /pjproject/trunk/pjlib/build/os-rtems.mak	(revision 433)
@@ -0,0 +1,46 @@
+#
+# PJLIB OS specific configuration for RTEMS
+#
+# Thanks Zetron, Inc. and Phil Torre <ptorre@zetron.com> for donating PJLIB
+# port to RTEMS.
+#
+
+#
+# PJLIB_OBJS specified here are object files to be included in PJLIB
+# (the library) for this specific operating system. Object files common 
+# to all operating systems should go in Makefile instead.
+#
+export PJLIB_OBJS += 	addr_resolv_sock.o guid_simple.o \
+			log_writer_stdout.o os_core_unix.o \
+			os_error_unix.o os_time_unix.o \
+			os_timestamp_common.o os_timestamp_posix.o \
+			pool_policy_malloc.o sock_bsd.o sock_select.o
+
+export PJLIB_OBJS += ioqueue_select.o 
+export PJLIB_OBJS += file_access_unistd.o file_io_ansi.o
+
+#
+# TEST_OBJS are operating system specific object files to be included in
+# the test application.
+#
+export TEST_OBJS +=	main_rtems.o
+
+#
+# RTEMS_LIBRARY_PATH points to the installed RTEMS libraries for the
+# desired target.  pjlib-test can't link without this.
+#
+export RTEMS_LIBRARY_PATH := $(RTEMS_LIBRARY_PATH)
+
+#
+# Additional LDFLAGS for pjlib-test
+#
+export TEST_LDFLAGS += 
+
+#
+# TARGETS are make targets in the Makefile, to be executed for this given
+# operating system.
+#
+export TARGETS	    =	pjlib pjlib-test
+
+
+
Index: /pjproject/trunk/pjlib/include/pj/compat/os_darwinos.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/compat/os_darwinos.h	(revision 432)
+++ /pjproject/trunk/pjlib/include/pj/compat/os_darwinos.h	(revision 433)
@@ -95,4 +95,8 @@
  */
 typedef int socklen_t;
+
+/* Set 1 if native sockaddr_in has sin_len member. 
+ * Default: 0
+ */
 #define PJ_SOCKADDR_HAS_LEN		1
 
@@ -106,4 +110,30 @@
 #define PJ_IOQUEUE_MAX_HANDLES		1024
 
+/**
+ * If this macro is set, it tells select I/O Queue that select() needs to
+ * be given correct value of nfds (i.e. largest fd + 1). This requires
+ * select ioqueue to re-scan the descriptors on each registration and
+ * unregistration.
+ * If this macro is not set, then ioqueue will always give FD_SETSIZE for
+ * nfds argument when calling select().
+ *
+ * Default: 0
+ */
+#define PJ_SELECT_NEEDS_NFDS		0
+
+/* If 1, use Read/Write mutex emulation for platforms that don't support it */
+#define PJ_EMULATE_RWMUTEX		0
+
+/* If 1, pj_thread_create() should enforce the stack size when creating 
+ * threads.
+ * Default: 0 (let OS decide the thread's stack size).
+ */
+#define PJ_THREAD_SET_STACK_SIZE    	0
+
+/* If 1, pj_thread_create() should allocate stack from the pool supplied.
+ * Default: 0 (let OS allocate memory for thread's stack).
+ */
+#define PJ_THREAD_ALLOCATE_STACK    	0
+
 
 #endif	/* __PJ_COMPAT_OS_DARWINOS_H__ */
Index: /pjproject/trunk/pjlib/include/pj/compat/os_linux.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/compat/os_linux.h	(revision 432)
+++ /pjproject/trunk/pjlib/include/pj/compat/os_linux.h	(revision 433)
@@ -55,5 +55,21 @@
 
 #define PJ_SOCK_HAS_INET_ATON	    1
+
+/* Set 1 if native sockaddr_in has sin_len member. 
+ * Default: 0
+ */
 #define PJ_SOCKADDR_HAS_LEN	    0
+
+/**
+ * If this macro is set, it tells select I/O Queue that select() needs to
+ * be given correct value of nfds (i.e. largest fd + 1). This requires
+ * select ioqueue to re-scan the descriptors on each registration and
+ * unregistration.
+ * If this macro is not set, then ioqueue will always give FD_SETSIZE for
+ * nfds argument when calling select().
+ *
+ * Default: 0
+ */
+#define PJ_SELECT_NEEDS_NFDS	    0
 
 /* Is errno a good way to retrieve OS errors?
@@ -90,4 +106,20 @@
 #define PJ_ATOMIC_VALUE_TYPE	    long
 
+/* If 1, use Read/Write mutex emulation for platforms that don't support it */
+#define PJ_EMULATE_RWMUTEX	    0
+
+/* If 1, pj_thread_create() should enforce the stack size when creating 
+ * threads.
+ * Default: 0 (let OS decide the thread's stack size).
+ */
+#define PJ_THREAD_SET_STACK_SIZE    	0
+
+/* If 1, pj_thread_create() should allocate stack from the pool supplied.
+ * Default: 0 (let OS allocate memory for thread's stack).
+ */
+#define PJ_THREAD_ALLOCATE_STACK    	0
+
+
+
 #endif	/* __PJ_COMPAT_OS_LINUX_H__ */
 
Index: /pjproject/trunk/pjlib/include/pj/compat/os_linux_kernel.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/compat/os_linux_kernel.h	(revision 432)
+++ /pjproject/trunk/pjlib/include/pj/compat/os_linux_kernel.h	(revision 433)
@@ -55,4 +55,8 @@
 
 #define PJ_SOCK_HAS_INET_ATON	    0
+
+/* Set 1 if native sockaddr_in has sin_len member. 
+ * Default: 0
+ */
 #define PJ_SOCKADDR_HAS_LEN	    0
 
@@ -61,4 +65,16 @@
  */
 #define PJ_HAS_SO_ERROR             1
+
+/**
+ * If this macro is set, it tells select I/O Queue that select() needs to
+ * be given correct value of nfds (i.e. largest fd + 1). This requires
+ * select ioqueue to re-scan the descriptors on each registration and
+ * unregistration.
+ * If this macro is not set, then ioqueue will always give FD_SETSIZE for
+ * nfds argument when calling select().
+ *
+ * Default: 0
+ */
+#define PJ_SELECT_NEEDS_NFDS	    0
 
 /* This value specifies the value set in errno by the OS when a non-blocking
@@ -105,4 +121,20 @@
 #define PJ_THREAD_DESC_SIZE	    128
 
+/* If 1, use Read/Write mutex emulation for platforms that don't support it */
+#define PJ_EMULATE_RWMUTEX	    0
+
+/* If 1, pj_thread_create() should enforce the stack size when creating 
+ * threads.
+ * Default: 0 (let OS decide the thread's stack size).
+ */
+#define PJ_THREAD_SET_STACK_SIZE    	0
+
+/* If 1, pj_thread_create() should allocate stack from the pool supplied.
+ * Default: 0 (let OS allocate memory for thread's stack).
+ */
+#define PJ_THREAD_ALLOCATE_STACK    	0
+
+
+
 #endif	/* __PJ_COMPAT_OS_LINUX_KERNEL_H__ */
 
Index: /pjproject/trunk/pjlib/include/pj/compat/os_palmos.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/compat/os_palmos.h	(revision 432)
+++ /pjproject/trunk/pjlib/include/pj/compat/os_palmos.h	(revision 433)
@@ -53,5 +53,21 @@
 
 #define PJ_SOCK_HAS_INET_ATON	    0
+
+/* Set 1 if native sockaddr_in has sin_len member. 
+ * Default: 0
+ */
 #define PJ_SOCKADDR_HAS_LEN	    0
+
+/**
+ * If this macro is set, it tells select I/O Queue that select() needs to
+ * be given correct value of nfds (i.e. largest fd + 1). This requires
+ * select ioqueue to re-scan the descriptors on each registration and
+ * unregistration.
+ * If this macro is not set, then ioqueue will always give FD_SETSIZE for
+ * nfds argument when calling select().
+ *
+ * Default: 0
+ */
+#define PJ_SELECT_NEEDS_NFDS	    0
 
 /* Is errno a good way to retrieve OS errors?
@@ -84,3 +100,19 @@
 #define PJ_NATIVE_STRING_IS_UNICODE	0
 
+/* If 1, use Read/Write mutex emulation for platforms that don't support it */
+#define PJ_EMULATE_RWMUTEX		1
+
+/* If 1, pj_thread_create() should enforce the stack size when creating 
+ * threads.
+ * Default: 0 (let OS decide the thread's stack size).
+ */
+#define PJ_THREAD_SET_STACK_SIZE    	0
+
+/* If 1, pj_thread_create() should allocate stack from the pool supplied.
+ * Default: 0 (let OS allocate memory for thread's stack).
+ */
+#define PJ_THREAD_ALLOCATE_STACK    	0
+
+
 #endif	/* __PJ_COMPAT_OS_PALMOS_H__ */
+
Index: /pjproject/trunk/pjlib/include/pj/compat/os_rtems.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/compat/os_rtems.h	(revision 433)
+++ /pjproject/trunk/pjlib/include/pj/compat/os_rtems.h	(revision 433)
@@ -0,0 +1,135 @@
+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+/*
+ * Thanks Zetron, Inc and Phil Torre <ptorre@zetron.com> for donating PJLIB
+ * port to RTEMS.
+ */
+
+#ifndef __PJ_COMPAT_OS_RTEMS_H__
+#define __PJ_COMPAT_OS_RTEMS_H__
+
+/**
+ * @file os_linux.h
+ * @brief Describes Linux operating system specifics.
+ */
+
+#define PJ_OS_NAME		    "rtems"
+
+#define PJ_HAS_ARPA_INET_H	    1
+#define PJ_HAS_ASSERT_H		    1
+#define PJ_HAS_CTYPE_H		    1
+#define PJ_HAS_ERRNO_H		    1
+#define PJ_HAS_LINUX_SOCKET_H	    0
+#define PJ_HAS_MALLOC_H		    1
+#define PJ_HAS_NETDB_H		    1
+#define PJ_HAS_NETINET_IN_H	    1
+#define PJ_HAS_SETJMP_H		    1
+#define PJ_HAS_STDARG_H		    0
+#define PJ_HAS_STDDEF_H		    1
+#define PJ_HAS_STDIO_H		    1
+#define PJ_HAS_STDLIB_H		    1
+#define PJ_HAS_STRING_H		    1
+#define PJ_HAS_SYS_IOCTL_H	    1
+#define PJ_HAS_SYS_SELECT_H	    1
+#define PJ_HAS_SYS_SOCKET_H	    1
+#define PJ_HAS_SYS_TIME_H	    1
+#define PJ_HAS_SYS_TIMEB_H	    1
+#define PJ_HAS_SYS_TYPES_H	    1
+#define PJ_HAS_TIME_H		    1
+#define PJ_HAS_UNISTD_H		    1
+
+#define PJ_HAS_MSWSOCK_H	    0
+#define PJ_HAS_WINSOCK_H	    0
+#define PJ_HAS_WINSOCK2_H	    0
+
+#define PJ_SOCK_HAS_INET_ATON	    1
+
+/* Set 1 if native sockaddr_in has sin_len member. 
+ * Default: 0
+ */
+#define PJ_SOCKADDR_HAS_LEN	    1
+
+/* Is errno a good way to retrieve OS errors?
+ */
+#define PJ_HAS_ERRNO_VAR	    1
+
+/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
+ * the status of non-blocking connect() operation.
+ */
+#define PJ_HAS_SO_ERROR             1
+
+/**
+ * If this macro is set, it tells select I/O Queue that select() needs to
+ * be given correct value of nfds (i.e. largest fd + 1). This requires
+ * select ioqueue to re-scan the descriptors on each registration and
+ * unregistration.
+ * If this macro is not set, then ioqueue will always give FD_SETSIZE for
+ * nfds argument when calling select().
+ *
+ * Default: 0
+ */
+#define PJ_SELECT_NEEDS_NFDS	    1
+
+/* This value specifies the value set in errno by the OS when a non-blocking
+ * socket recv() can not return immediate daata.
+ */
+#define PJ_BLOCKING_ERROR_VAL       EWOULDBLOCK
+
+/* This value specifies the value set in errno by the OS when a non-blocking
+ * socket connect() can not get connected immediately.
+ */
+#define PJ_BLOCKING_CONNECT_ERROR_VAL   EINPROGRESS
+
+/* Default threading is enabled, unless it's overridden. */
+#ifndef PJ_HAS_THREADS
+#  define PJ_HAS_THREADS	    (1)
+#endif
+
+#define PJ_HAS_HIGH_RES_TIMER	    1
+#define PJ_HAS_MALLOC               1
+#ifndef PJ_OS_HAS_CHECK_STACK
+#   define PJ_OS_HAS_CHECK_STACK    0
+#endif
+#define PJ_NATIVE_STRING_IS_UNICODE 0
+
+#define PJ_ATOMIC_VALUE_TYPE	    int
+
+/* If 1, use Read/Write mutex emulation for platforms that don't support it */
+#define PJ_EMULATE_RWMUTEX	    1
+
+/* Missing socklen_t */
+typedef int socklen_t;
+
+/* If 1, pj_thread_create() should enforce the stack size when creating 
+ * threads.
+ * Default: 0 (let OS decide the thread's stack size).
+ */
+#define PJ_THREAD_SET_STACK_SIZE    1
+
+/* If 1, pj_thread_create() should allocate stack from the pool supplied.
+ * Default: 0 (let OS allocate memory for thread's stack).
+ */
+#define PJ_THREAD_ALLOCATE_STACK    1
+
+
+
+
+#endif	/* __PJ_COMPAT_OS_RTEMS_H__ */
+
Index: /pjproject/trunk/pjlib/include/pj/compat/os_sunos.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/compat/os_sunos.h	(revision 432)
+++ /pjproject/trunk/pjlib/include/pj/compat/os_sunos.h	(revision 433)
@@ -55,4 +55,8 @@
 
 #define PJ_SOCK_HAS_INET_ATON	    0
+
+/* Set 1 if native sockaddr_in has sin_len member. 
+ * Default: 0
+ */
 #define PJ_SOCKADDR_HAS_LEN	    0
 
@@ -76,4 +80,16 @@
 #define PJ_BLOCKING_CONNECT_ERROR_VAL   EINPROGRESS
 
+/**
+ * If this macro is set, it tells select I/O Queue that select() needs to
+ * be given correct value of nfds (i.e. largest fd + 1). This requires
+ * select ioqueue to re-scan the descriptors on each registration and
+ * unregistration.
+ * If this macro is not set, then ioqueue will always give FD_SETSIZE for
+ * nfds argument when calling select().
+ *
+ * Default: 0
+ */
+#define PJ_SELECT_NEEDS_NFDS		0
+
 /* Default threading is enabled, unless it's overridden. */
 #ifndef PJ_HAS_THREADS
@@ -93,4 +109,20 @@
 #define BSD_COMP
 
+/* If 1, use Read/Write mutex emulation for platforms that don't support it */
+#define PJ_EMULATE_RWMUTEX		0
+
+/* If 1, pj_thread_create() should enforce the stack size when creating 
+ * threads.
+ * Default: 0 (let OS decide the thread's stack size).
+ */
+#define PJ_THREAD_SET_STACK_SIZE    	0
+
+/* If 1, pj_thread_create() should allocate stack from the pool supplied.
+ * Default: 0 (let OS allocate memory for thread's stack).
+ */
+#define PJ_THREAD_ALLOCATE_STACK    	0
+
+
+
 #endif	/* __PJ_COMPAT_OS_SUNOS_H__ */
 
Index: /pjproject/trunk/pjlib/include/pj/compat/os_win32.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/compat/os_win32.h	(revision 432)
+++ /pjproject/trunk/pjlib/include/pj/compat/os_win32.h	(revision 433)
@@ -61,4 +61,8 @@
 
 #define PJ_SOCK_HAS_INET_ATON	    0
+
+/* Set 1 if native sockaddr_in has sin_len member. 
+ * Default: 0
+ */
 #define PJ_SOCKADDR_HAS_LEN	    0
 
@@ -82,4 +86,16 @@
 #define PJ_BLOCKING_CONNECT_ERROR_VAL   WSAEWOULDBLOCK
 
+/**
+ * If this macro is set, it tells select I/O Queue that select() needs to
+ * be given correct value of nfds (i.e. largest fd + 1). This requires
+ * select ioqueue to re-scan the descriptors on each registration and
+ * unregistration.
+ * If this macro is not set, then ioqueue will always give FD_SETSIZE for
+ * nfds argument when calling select().
+ *
+ * Default: 0
+ */
+#define PJ_SELECT_NEEDS_NFDS		0
+
 /* Default threading is enabled, unless it's overridden. */
 #ifndef PJ_HAS_THREADS
@@ -96,3 +112,19 @@
 #define PJ_ATOMIC_VALUE_TYPE		long
 
+/* If 1, use Read/Write mutex emulation for platforms that don't support it */
+#define PJ_EMULATE_RWMUTEX		1
+
+/* If 1, pj_thread_create() should enforce the stack size when creating 
+ * threads.
+ * Default: 0 (let OS decide the thread's stack size).
+ */
+#define PJ_THREAD_SET_STACK_SIZE    	0
+
+/* If 1, pj_thread_create() should allocate stack from the pool supplied.
+ * Default: 0 (let OS allocate memory for thread's stack).
+ */
+#define PJ_THREAD_ALLOCATE_STACK    	0
+
+
 #endif	/* __PJ_COMPAT_OS_WIN32_H__ */
+
Index: /pjproject/trunk/pjlib/include/pj/compat/os_win32_wince.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/compat/os_win32_wince.h	(revision 432)
+++ /pjproject/trunk/pjlib/include/pj/compat/os_win32_wince.h	(revision 433)
@@ -59,4 +59,8 @@
 
 #define PJ_SOCK_HAS_INET_ATON	    0
+
+/* Set 1 if native sockaddr_in has sin_len member. 
+ * Default: 0
+ */
 #define PJ_SOCKADDR_HAS_LEN	    0
 
@@ -79,4 +83,16 @@
  */
 #define PJ_BLOCKING_CONNECT_ERROR_VAL   WSAEWOULDBLOCK
+
+/**
+ * If this macro is set, it tells select I/O Queue that select() needs to
+ * be given correct value of nfds (i.e. largest fd + 1). This requires
+ * select ioqueue to re-scan the descriptors on each registration and
+ * unregistration.
+ * If this macro is not set, then ioqueue will always give FD_SETSIZE for
+ * nfds argument when calling select().
+ *
+ * Default: 0
+ */
+#define PJ_SELECT_NEEDS_NFDS	    0
 
 /* Default threading is enabled, unless it's overridden. */
@@ -103,4 +119,19 @@
 #define PJ_NATIVE_STRING_IS_UNICODE 1
 
+/* If 1, use Read/Write mutex emulation for platforms that don't support it */
+#define PJ_EMULATE_RWMUTEX	    1
+
+/* If 1, pj_thread_create() should enforce the stack size when creating 
+ * threads.
+ * Default: 0 (let OS decide the thread's stack size).
+ */
+#define PJ_THREAD_SET_STACK_SIZE    	0
+
+/* If 1, pj_thread_create() should allocate stack from the pool supplied.
+ * Default: 0 (let OS allocate memory for thread's stack).
+ */
+#define PJ_THREAD_ALLOCATE_STACK    	0
+
+
 #endif	/* __PJ_COMPAT_OS_WIN32_WINCE_H__ */
 
Index: /pjproject/trunk/pjlib/include/pj/config.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/config.h	(revision 432)
+++ /pjproject/trunk/pjlib/include/pj/config.h	(revision 433)
@@ -54,4 +54,6 @@
 #elif defined(PJ_DARWINOS) && PJ_DARWINOS!=0
 #  include <pj/compat/os_darwinos.h>
+#elif defined(PJ_RTEMS) && PJ_RTEMS!=0
+#  include <pj/compat/os_rtems.h>
 #else
 #  error "Please specify target os."
@@ -224,4 +226,15 @@
 
 /**
+ * Specify this as \a stack_size argument in #pj_thread_create() to specify
+ * that thread should use default stack size for the current platform.
+ *
+ * Default: 8192
+ */
+#ifndef PJ_THREAD_DEFAULT_STACK_SIZE 
+#  define PJ_THREAD_DEFAULT_STACK_SIZE    8192
+#endif
+
+
+/**
  * Do we have alternate pool implementation?
  *
@@ -557,5 +570,15 @@
 #endif
 
-
+#if !defined(PJ_EMULATE_RWMUTEX)
+#  error "PJ_EMULATE_RWMUTEX should be defined in compat/os_xx.h"
+#endif
+
+#if !defined(PJ_THREAD_SET_STACK_SIZE)
+#  error "PJ_THREAD_SET_STACK_SIZE should be defined in compat/os_xx.h"
+#endif
+
+#if !defined(PJ_THREAD_ALLOCATE_STACK)
+#  error "PJ_THREAD_ALLOCATE_STACK should be defined in compat/os_xx.h"
+#endif
 
 PJ_BEGIN_DECL
Index: /pjproject/trunk/pjlib/include/pj/os.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/os.h	(revision 432)
+++ /pjproject/trunk/pjlib/include/pj/os.h	(revision 433)
@@ -58,10 +58,4 @@
 } pj_thread_create_flags;
 
-
-/**
- * Specify this as \a stack_size argument in #pj_thread_create() to specify
- * that thread should use default stack size for the current platform.
- */
-#define PJ_THREAD_DEFAULT_STACK_SIZE    0
 
 /**
@@ -162,10 +156,11 @@
 
 /**
- * Join thread.
- * This function will block the caller thread until the specified thread exits.
+ * Join thread, and block the caller thread until the specified thread exits.
+ * If the specified thread has already been dead, or it does not exist,
+ * the function will return immediately with successfull status.
  *
  * @param thread    The thread handle.
  *
- * @return zero on success.
+ * @return PJ_SUCCESS on success.
  */
 PJ_DECL(pj_status_t) pj_thread_join(pj_thread_t *thread);
Index: /pjproject/trunk/pjlib/src/pj/hash.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/hash.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pj/hash.c	(revision 433)
@@ -50,5 +50,6 @@
 
 
-PJ_DEF(pj_uint32_t) pj_hash_calc(pj_uint32_t hash, const void *key, unsigned keylen)
+PJ_DEF(pj_uint32_t) pj_hash_calc(pj_uint32_t hash, const void *key, 
+				 unsigned keylen)
 {
     PJ_CHECK_STACK();
@@ -57,5 +58,5 @@
 	const unsigned char *p = key;
 	for ( ; *p; ++p ) {
-	    hash = hash * PJ_HASH_MULTIPLIER + *p;
+	    hash = (hash * PJ_HASH_MULTIPLIER) + *p;
 	}
     } else {
@@ -63,5 +64,5 @@
 			    *end = p + keylen;
 	for ( ; p!=end; ++p) {
-	    hash = hash * PJ_HASH_MULTIPLIER + *p;
+	    hash = (hash * PJ_HASH_MULTIPLIER) + *p;
 	}
     }
Index: /pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c	(revision 433)
@@ -238,5 +238,5 @@
 
 	    gp_rc = getpeername(h->fd, (struct sockaddr*)&addr, &addrlen);
-	    bytes_transfered = gp_rc;
+	    bytes_transfered = (gp_rc < 0) ? gp_rc : -gp_rc;
 	}
 #endif
Index: /pjproject/trunk/pjlib/src/pj/ioqueue_select.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/ioqueue_select.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pj/ioqueue_select.c	(revision 433)
@@ -94,4 +94,10 @@
 #define VALIDATE_FD_SET     0
 
+#if 0
+#  define TRACE__(args)	PJ_LOG(3,args)
+#else
+#  define TRACE__(args)
+#endif
+
 /*
  * This describes each key.
@@ -109,6 +115,7 @@
     DECLARE_COMMON_IOQUEUE
 
-    unsigned		max, count;
-    pj_ioqueue_key_t	active_list;
+    unsigned		max, count;	/* Max and current key count	    */
+    int			nfds;		/* The largest fd value (for select)*/
+    pj_ioqueue_key_t	active_list;	/* List of active keys.		    */
     pj_fd_set_t		rfdset;
     pj_fd_set_t		wfdset;
@@ -136,4 +143,30 @@
     return "select";
 }
+
+/* 
+ * Scan the socket descriptor sets for the largest descriptor.
+ * This value is needed by select().
+ */
+#if defined(PJ_SELECT_NEEDS_NFDS) && PJ_SELECT_NEEDS_NFDS!=0
+static void rescan_fdset(pj_ioqueue_t *ioqueue)
+{
+    pj_ioqueue_key_t *key = ioqueue->active_list.next;
+    int max = 0;
+
+    while (key != &ioqueue->active_list) {
+	if (key->fd > max)
+	    max = key->fd;
+	key = key->next;
+    }
+
+    ioqueue->nfds = max;
+}
+#else
+static void rescan_fdset(pj_ioqueue_t *ioqueue)
+{
+    ioqueue->nfds = FD_SETSIZE-1;
+}
+#endif
+
 
 /*
@@ -172,4 +205,6 @@
 #endif
     pj_list_init(&ioqueue->active_list);
+
+    rescan_fdset(ioqueue);
 
 #if PJ_IOQUEUE_HAS_SAFE_UNREG
@@ -333,4 +368,7 @@
     ++ioqueue->count;
 
+    /* Rescan fdset to get max descriptor */
+    rescan_fdset(ioqueue);
+
 on_return:
     /* On error, socket may be left in non-blocking mode. */
@@ -369,4 +407,6 @@
 	pj_list_erase(key);
 	pj_list_push_back(&key->ioqueue->closing_list, key);
+	/* Rescan fdset to get max descriptor */
+	rescan_fdset(key->ioqueue);
 	pj_lock_release(key->ioqueue->lock);
     }
@@ -612,4 +652,5 @@
 #endif
 	pj_lock_release(ioqueue->lock);
+	TRACE__((THIS_FILE, "     poll: no fd is set"));
         if (timeout)
             pj_thread_sleep(PJ_TIME_VAL_MSEC(*timeout));
@@ -633,5 +674,6 @@
     pj_lock_release(ioqueue->lock);
 
-    count = pj_sock_select(FD_SETSIZE, &rfdset, &wfdset, &xfdset, timeout);
+    count = pj_sock_select(ioqueue->nfds+1, &rfdset, &wfdset, &xfdset, 
+			   timeout);
     
     if (count <= 0)
Index: /pjproject/trunk/pjlib/src/pj/os_core_unix.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/os_core_unix.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pj/os_core_unix.c	(revision 433)
@@ -17,4 +17,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  */
+/*
+ * Contributors:
+ * - Thanks for Zetron, Inc. (Phil Torre, ptorre@zetron.com) for donating
+ *   the RTEMS port.
+ */
 #define _GNU_SOURCE
 #include <pj/os.h>
@@ -154,5 +159,5 @@
 #endif   
 
-    PJ_LOG(4,(THIS_FILE, "pjlib %s for Unix initialized",
+    PJ_LOG(4,(THIS_FILE, "pjlib %s for POSIX initialized",
 	      PJ_VERSION));
 
@@ -197,4 +202,6 @@
 	//*thread_ptr = (pj_thread_t*)pj_thread_local_get (thread_tls_id);
         //return PJ_SUCCESS;
+	PJ_LOG(4,(THIS_FILE, "Info: possibly re-registering existing "
+			     "thread"));
     }
 
@@ -282,4 +289,5 @@
     /* Done. */
     PJ_LOG(6,(rec->obj_name, "Thread quitting"));
+
     return result;
 }
@@ -299,5 +307,9 @@
 #if PJ_HAS_THREADS
     pj_thread_t *rec;
+    pthread_attr_t thread_attr;
+    void *stack_addr;
     int rc;
+
+    PJ_UNUSED_ARG(stack_addr);
 
     PJ_CHECK_STACK();
@@ -306,6 +318,5 @@
     /* Create thread record and assign name for the thread */
     rec = (struct pj_thread_t*) pj_pool_zalloc(pool, sizeof(pj_thread_t));
-    if (!rec)
-	return PJ_ENOMEM;
+    PJ_ASSERT_RETURN(rec, PJ_ENOMEM);
     
     /* Set name. */
@@ -320,6 +331,10 @@
     }
 
+    /* Set default stack size */
+    if (stack_size == 0)
+	stack_size = PJ_THREAD_DEFAULT_STACK_SIZE;
+
 #if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
-    rec->stk_size = stack_size ? stack_size : 0xFFFFFFFFUL;
+    rec->stk_size = stack_size;
     rec->stk_max_usage = 0;
 #endif
@@ -328,6 +343,7 @@
     if (flags & PJ_THREAD_SUSPENDED) {
 	rc = pj_mutex_create_simple(pool, NULL, &rec->suspended_mutex);
-	if (rc != PJ_SUCCESS)
+	if (rc != PJ_SUCCESS) {
 	    return rc;
+	}
 
 	pj_mutex_lock(rec->suspended_mutex);
@@ -336,14 +352,38 @@
     }
     
-    PJ_LOG(6, (rec->obj_name, "Thread created"));
+
+    /* Init thread attributes */
+    pthread_attr_init(&thread_attr);
+
+#if defined(PJ_THREAD_SET_STACK_SIZE) && PJ_THREAD_SET_STACK_SIZE!=0
+    /* Set thread's stack size */
+    rc = pthread_attr_setstacksize(&thread_attr, stack_size);
+    if (rc != 0)
+	return PJ_RETURN_OS_ERROR(rc);
+#endif	/* PJ_THREAD_SET_STACK_SIZE */
+
+
+#if defined(PJ_THREAD_ALLOCATE_STACK) && PJ_THREAD_ALLOCATE_STACK!=0
+    /* Allocate memory for the stack */
+    stack_addr = pj_pool_alloc(pool, stack_size);
+    PJ_ASSERT_RETURN(stack_addr, PJ_ENOMEM);
+
+    rc = pthread_attr_setstackaddr(&thread_attr, stack_addr);
+    if (rc != 0)
+	return PJ_RETURN_OS_ERROR(rc);
+#endif	/* PJ_THREAD_ALLOCATE_STACK */
+
 
     /* Create the thread. */
     rec->proc = proc;
     rec->arg = arg;
-    rc = pthread_create( &rec->thread, NULL, thread_main, rec);
-    if (rc != 0)
+    rc = pthread_create( &rec->thread, &thread_attr, &thread_main, rec);
+    if (rc != 0) {
 	return PJ_RETURN_OS_ERROR(rc);
+    }
 
     *ptr_thread = rec;
+
+    PJ_LOG(6, (rec->obj_name, "Thread created"));
     return PJ_SUCCESS;
 #else
@@ -424,6 +464,11 @@
     if (result == 0)
 	return PJ_SUCCESS;
-    else
-	return PJ_RETURN_OS_ERROR(result);
+    else {
+	/* Calling pthread_join() on a thread that no longer exists and 
+	 * getting back ESRCH isn't an error (in this context). 
+	 * Thanks Phil Torre <ptorre@zetron.com>.
+	 */
+	return result==ESRCH ? PJ_SUCCESS : PJ_RETURN_OS_ERROR(result);
+    }
 #else
     PJ_CHECK_STACK();
@@ -438,8 +483,12 @@
 PJ_DEF(pj_status_t) pj_thread_destroy(pj_thread_t *p)
 {
-    /* This function is used to destroy thread handle in other platforms.
-     * I suppose there's nothing to do here..
-     */
-    PJ_CHECK_STACK();
+    PJ_CHECK_STACK();
+
+    /* Destroy mutex used to suspend thread */
+    if (p->suspended_mutex) {
+	pj_mutex_destroy(p->suspended_mutex);
+	p->suspended_mutex = NULL;
+    }
+
     return PJ_SUCCESS;
 }
@@ -450,6 +499,24 @@
 PJ_DEF(pj_status_t) pj_thread_sleep(unsigned msec)
 {
-    PJ_CHECK_STACK();
-    return usleep(msec * 1000);
+/* TODO: should change this to something like PJ_OS_HAS_NANOSLEEP */
+#if defined(PJ_RTEMS) && PJ_RTEMS!=0
+    enum { NANOSEC_PER_MSEC = 1000000 };
+    struct timespec req;
+
+    PJ_CHECK_STACK();
+    req.tv_sec = msec / 1000;
+    req.tv_nsec = (msec % 1000) * NANOSEC_PER_MSEC;
+
+    if (nanosleep(&req, NULL) == 0)
+	return PJ_SUCCESS;
+
+    return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+#else
+    PJ_CHECK_STACK();
+    if (usleep(msec * 1000) == 0)
+	return PJ_SUCCESS;
+
+    return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+#endif	/* PJ_RTEMS */
 }
 
@@ -514,6 +581,5 @@
     pj_status_t rc;
     pj_atomic_t *atomic_var = pj_pool_calloc(pool, 1, sizeof(pj_atomic_t));
-    if (!atomic_var)
-	return PJ_ENOMEM;
+    PJ_ASSERT_RETURN(atomic_var, PJ_ENOMEM);
     
 #if PJ_HAS_THREADS
@@ -766,5 +832,7 @@
     PJ_CHECK_STACK();
 
-    pthread_mutexattr_init(&attr);
+    rc = pthread_mutexattr_init(&attr);
+    if (rc != 0)
+	return PJ_RETURN_OS_ERROR(rc);
 
     if (type == PJ_MUTEX_SIMPLE) {
@@ -772,4 +840,6 @@
 	extern int pthread_mutexattr_settype(pthread_mutexattr_t*,int);
 	rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_FAST_NP);
+#elif defined(PJ_RTEMS) && PJ_RTEMS!=0
+	/* Nothing to do, default is simple */
 #else
 	rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
@@ -779,4 +849,11 @@
 	extern int pthread_mutexattr_settype(pthread_mutexattr_t*,int);
 	rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+#elif defined(PJ_RTEMS) && PJ_RTEMS!=0
+	// Phil Torre <ptorre@zetron.com>:
+	// The RTEMS implementation of POSIX mutexes doesn't include 
+	// pthread_mutexattr_settype(), so what follows is a hack
+	// until I get RTEMS patched to support the set/get functions.
+	PJ_TODO(FIX_RTEMS_RECURSIVE_MUTEX_TYPE)
+	attr.recursive = 1;
 #else
 	rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
@@ -832,5 +909,5 @@
 
     mutex = pj_pool_alloc(pool, sizeof(*mutex));
-    if (!mutex) return PJ_ENOMEM;
+    PJ_ASSERT_RETURN(mutex, PJ_ENOMEM);
 
     if ((rc=init_mutex(mutex, name, type)) != PJ_SUCCESS)
@@ -1003,4 +1080,11 @@
 
 ///////////////////////////////////////////////////////////////////////////////
+/*
+ * Include Read/Write mutex emulation for POSIX platforms that lack it (e.g.
+ * RTEMS). Otherwise use POSIX rwlock.
+ */
+#if defined(PJ_EMULATE_RWMUTEX) && PJ_EMULATE_RWMUTEX!=0
+#  include "os_rwmutex.c"
+#else
 struct pj_rwmutex_t
 {
@@ -1095,4 +1179,7 @@
     return PJ_SUCCESS;
 }
+
+#endif	/* PJ_EMULATE_RWMUTEX */
+
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1114,6 +1201,6 @@
     PJ_ASSERT_RETURN(pool != NULL && ptr_sem != NULL, PJ_EINVAL);
 
-    sem = pj_pool_alloc(pool, sizeof(*sem));    
-    if (!sem) return PJ_ENOMEM;
+    sem = pj_pool_alloc(pool, sizeof(*sem));
+    PJ_ASSERT_RETURN(sem, PJ_ENOMEM);
 
     if (sem_init( &sem->sem, 0, initial) != 0) 
Index: /pjproject/trunk/pjlib/src/pj/os_rwmutex.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/os_rwmutex.c	(revision 433)
+++ /pjproject/trunk/pjlib/src/pj/os_rwmutex.c	(revision 433)
@@ -0,0 +1,162 @@
+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+/* 
+ * Note: 
+ * 
+ * DO NOT BUILD THIS FILE DIRECTLY. THIS FILE WILL BE INCLUDED BY os_core_*.c
+ * WHEN MACRO PJ_EMULATE_RWMUTEX IS SET.
+ */
+
+/*
+ * os_rwmutex.c:
+ *
+ * Implementation of Read-Write mutex for platforms that lack it (e.g.
+ * Win32, RTEMS).
+ */
+
+
+struct pj_rwmutex_t
+{
+    pj_mutex_t *read_lock;
+    /* write_lock must use semaphore, because write_lock may be released
+     * by thread other than the thread that acquire the write_lock in the
+     * first place.
+     */
+    pj_sem_t   *write_lock;
+    pj_int32_t  reader_count;
+};
+
+/*
+ * Create reader/writer mutex.
+ *
+ */
+PJ_DEF(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name,
+				      pj_rwmutex_t **p_mutex)
+{
+    pj_status_t status;
+    pj_rwmutex_t *rwmutex;
+
+    PJ_ASSERT_RETURN(pool && p_mutex, PJ_EINVAL);
+
+    *p_mutex = NULL;
+    rwmutex = pj_pool_alloc(pool, sizeof(struct pj_rwmutex_t));
+
+    status = pj_mutex_create_simple(pool, name, &rwmutex ->read_lock);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    status = pj_sem_create(pool, name, 1, 1, &rwmutex->write_lock);
+    if (status != PJ_SUCCESS) {
+	pj_mutex_destroy(rwmutex->read_lock);
+	return status;
+    }
+
+    rwmutex->reader_count = 0;
+    *p_mutex = rwmutex;
+    return PJ_SUCCESS;
+}
+
+/*
+ * Lock the mutex for reading.
+ *
+ */
+PJ_DEF(pj_status_t) pj_rwmutex_lock_read(pj_rwmutex_t *mutex)
+{
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
+
+    status = pj_mutex_lock(mutex->read_lock);
+    if (status != PJ_SUCCESS) {
+	pj_assert(!"This pretty much is unexpected");
+	return status;
+    }
+
+    mutex->reader_count++;
+
+    pj_assert(mutex->reader_count < 0x7FFFFFF0L);
+
+    if (mutex->reader_count == 1)
+	pj_sem_wait(mutex->write_lock);
+
+    status = pj_mutex_unlock(mutex->read_lock);
+    return status;
+}
+
+/*
+ * Lock the mutex for writing.
+ *
+ */
+PJ_DEF(pj_status_t) pj_rwmutex_lock_write(pj_rwmutex_t *mutex)
+{
+    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
+    return pj_sem_wait(mutex->write_lock);
+}
+
+/*
+ * Release read lock.
+ *
+ */
+PJ_DEF(pj_status_t) pj_rwmutex_unlock_read(pj_rwmutex_t *mutex)
+{
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
+
+    status = pj_mutex_lock(mutex->read_lock);
+    if (status != PJ_SUCCESS) {
+	pj_assert(!"This pretty much is unexpected");
+	return status;
+    }
+
+    pj_assert(mutex->reader_count >= 1);
+
+    --mutex->reader_count;
+    if (mutex->reader_count == 0)
+	pj_sem_post(mutex->write_lock);
+
+    status = pj_mutex_unlock(mutex->read_lock);
+    return status;
+}
+
+/*
+ * Release write lock.
+ *
+ */
+PJ_DEF(pj_status_t) pj_rwmutex_unlock_write(pj_rwmutex_t *mutex)
+{
+    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
+    pj_assert(mutex->reader_count <= 1);
+    return pj_sem_post(mutex->write_lock);
+}
+
+
+/*
+ * Destroy reader/writer mutex.
+ *
+ */
+PJ_DEF(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex)
+{
+    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
+    pj_mutex_destroy(mutex->read_lock);
+    pj_sem_destroy(mutex->write_lock);
+    return PJ_SUCCESS;
+}
+
Index: /pjproject/trunk/pjlib/src/pj/os_time_unix.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/os_time_unix.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pj/os_time_unix.c	(revision 433)
@@ -18,4 +18,5 @@
  */
 #include <pj/os.h>
+#include <pj/errno.h>
 #include <pj/compat/time.h>
 
@@ -24,15 +25,21 @@
 #endif
 
+#include <errno.h>
+
 ///////////////////////////////////////////////////////////////////////////////
 
 PJ_DEF(pj_status_t) pj_gettimeofday(pj_time_val *p_tv)
 {
-    struct timeval tv;
+    struct timeval the_time;
+    int rc;
 
     PJ_CHECK_STACK();
 
-    gettimeofday(&tv, NULL);
-    p_tv->sec = tv.tv_sec;
-    p_tv->msec = tv.tv_usec / 1000;
+    rc = gettimeofday(&the_time, NULL);
+    if (rc != 0)
+	return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+
+    p_tv->sec = the_time.tv_sec;
+    p_tv->msec = the_time.tv_usec / 1000;
     return PJ_SUCCESS;
 }
Index: project/trunk/pjlib/src/pj/os_timestamp_linux.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/os_timestamp_linux.c	(revision 432)
+++ 	(revision )
@@ -1,142 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
- */
-#include <pj/os.h>
-#include <pj/errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#if defined(PJ_HAS_PENTIUM) && PJ_HAS_PENTIUM!=0 && \
-    defined(PJ_TIMESTAMP_USE_RDTSC) && PJ_TIMESTAMP_USE_RDTSC!=0 && \
-    defined(PJ_M_I386) && PJ_M_I386!=0 && \
-    defined(PJ_LINUX) && PJ_LINUX!=0
-static int machine_speed_mhz;
-static pj_timestamp machine_speed;
-
-static __inline__ unsigned long long int rdtsc()
-{
-    unsigned long long int x;
-    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
-    return x;
-}
-
-/* Determine machine's CPU MHz to get the counter's frequency.
- */
-static int get_machine_speed_mhz()
-{
-    FILE *strm;
-    char buf[512];
-    int len;
-    char *pos, *end;
-	
-    PJ_CHECK_STACK();
-	
-    /* Open /proc/cpuinfo and read the file */
-    strm = fopen("/proc/cpuinfo", "r");
-    if (!strm)
-        return -1;
-    len = fread(buf, 1, sizeof(buf), strm);
-    fclose(strm);
-    if (len < 1) {
-        return -1;
-    }
-    buf[len] = '\0';
-
-    /* Locate the MHz digit. */
-    pos = strstr(buf, "cpu MHz");
-    if (!pos)
-        return -1;
-    pos = strchr(pos, ':');
-    if (!pos)
-        return -1;
-    end = (pos += 2);
-    while (isdigit(*end)) ++end;
-    *end = '\0';
-
-    /* Return the Mhz part, and give it a +1. */
-    return atoi(pos)+1;
-}
-
-PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts)
-{
-    if (machine_speed_mhz == 0) {
-	machine_speed_mhz = get_machine_speed_mhz();
-	if (machine_speed_mhz > 0) {
-	    machine_speed.u64 = machine_speed_mhz * 1000000.0;
-	}
-    }
-    
-    if (machine_speed_mhz == -1) {
-	ts->u64 = 0;
-	return -1;
-    } 
-    ts->u64 = rdtsc();
-    return 0;
-}
-
-PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq)
-{
-    if (machine_speed_mhz == 0) {
-	machine_speed_mhz = get_machine_speed_mhz();
-	if (machine_speed_mhz > 0) {
-	    machine_speed.u64 = machine_speed_mhz * 1000000.0;
-	}
-    }
-    
-    if (machine_speed_mhz == -1) {
-	freq->u64 = 1;	/* return 1 to prevent division by zero in apps. */
-	return -1;
-    } 
-
-    freq->u64 = machine_speed.u64;
-    return 0;
-}
-
-#else
-#include <sys/time.h>
-#include <errno.h>
-
-#define USEC_PER_SEC	1000000
-
-PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts)
-{
-    struct timeval tv;
-
-    if (gettimeofday(&tv, NULL) != 0) {
-	return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
-    }
-
-    ts->u64 = tv.tv_sec;
-    ts->u64 *= USEC_PER_SEC;
-    ts->u64 += tv.tv_usec;
-
-    return PJ_SUCCESS;
-}
-
-PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq)
-{
-    freq->u32.hi = 0;
-    freq->u32.lo = USEC_PER_SEC;
-
-    return PJ_SUCCESS;
-}
-
-#endif
-
Index: /pjproject/trunk/pjlib/src/pj/os_timestamp_posix.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/os_timestamp_posix.c	(revision 433)
+++ /pjproject/trunk/pjlib/src/pj/os_timestamp_posix.c	(revision 433)
@@ -0,0 +1,142 @@
+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/os.h>
+#include <pj/errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#if defined(PJ_HAS_PENTIUM) && PJ_HAS_PENTIUM!=0 && \
+    defined(PJ_TIMESTAMP_USE_RDTSC) && PJ_TIMESTAMP_USE_RDTSC!=0 && \
+    defined(PJ_M_I386) && PJ_M_I386!=0 && \
+    defined(PJ_LINUX) && PJ_LINUX!=0
+static int machine_speed_mhz;
+static pj_timestamp machine_speed;
+
+static __inline__ unsigned long long int rdtsc()
+{
+    unsigned long long int x;
+    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
+    return x;
+}
+
+/* Determine machine's CPU MHz to get the counter's frequency.
+ */
+static int get_machine_speed_mhz()
+{
+    FILE *strm;
+    char buf[512];
+    int len;
+    char *pos, *end;
+	
+    PJ_CHECK_STACK();
+	
+    /* Open /proc/cpuinfo and read the file */
+    strm = fopen("/proc/cpuinfo", "r");
+    if (!strm)
+        return -1;
+    len = fread(buf, 1, sizeof(buf), strm);
+    fclose(strm);
+    if (len < 1) {
+        return -1;
+    }
+    buf[len] = '\0';
+
+    /* Locate the MHz digit. */
+    pos = strstr(buf, "cpu MHz");
+    if (!pos)
+        return -1;
+    pos = strchr(pos, ':');
+    if (!pos)
+        return -1;
+    end = (pos += 2);
+    while (isdigit(*end)) ++end;
+    *end = '\0';
+
+    /* Return the Mhz part, and give it a +1. */
+    return atoi(pos)+1;
+}
+
+PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts)
+{
+    if (machine_speed_mhz == 0) {
+	machine_speed_mhz = get_machine_speed_mhz();
+	if (machine_speed_mhz > 0) {
+	    machine_speed.u64 = machine_speed_mhz * 1000000.0;
+	}
+    }
+    
+    if (machine_speed_mhz == -1) {
+	ts->u64 = 0;
+	return -1;
+    } 
+    ts->u64 = rdtsc();
+    return 0;
+}
+
+PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq)
+{
+    if (machine_speed_mhz == 0) {
+	machine_speed_mhz = get_machine_speed_mhz();
+	if (machine_speed_mhz > 0) {
+	    machine_speed.u64 = machine_speed_mhz * 1000000.0;
+	}
+    }
+    
+    if (machine_speed_mhz == -1) {
+	freq->u64 = 1;	/* return 1 to prevent division by zero in apps. */
+	return -1;
+    } 
+
+    freq->u64 = machine_speed.u64;
+    return 0;
+}
+
+#else
+#include <sys/time.h>
+#include <errno.h>
+
+#define USEC_PER_SEC	1000000
+
+PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts)
+{
+    struct timeval tv;
+
+    if (gettimeofday(&tv, NULL) != 0) {
+	return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+    }
+
+    ts->u64 = tv.tv_sec;
+    ts->u64 *= USEC_PER_SEC;
+    ts->u64 += tv.tv_usec;
+
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq)
+{
+    freq->u32.hi = 0;
+    freq->u32.lo = USEC_PER_SEC;
+
+    return PJ_SUCCESS;
+}
+
+#endif
+
Index: /pjproject/trunk/pjlib/src/pj/pool.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/pool.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pj/pool.c	(revision 433)
@@ -174,4 +174,9 @@
     PJ_CHECK_STACK();
 
+    /* If callback is NULL, set calback from the policy */
+    if (callback == NULL)
+	callback = f->policy.callback;
+
+    /* Allocate initial block */
     buffer = (*f->policy.block_alloc)(f, initial_size);
     if (!buffer)
Index: /pjproject/trunk/pjlib/src/pj/sock_bsd.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/sock_bsd.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pj/sock_bsd.c	(revision 433)
@@ -27,5 +27,5 @@
 /*
  * Address families conversion.
- * The values here are indexed based on pj_addr_family-0xFF00.
+ * The values here are indexed based on pj_addr_family.
  */
 const pj_uint16_t PJ_AF_UNIX	= AF_UNIX;
@@ -45,5 +45,5 @@
 /*
  * Socket types conversion.
- * The values here are indexed based on pj_sock_type-0xFF00
+ * The values here are indexed based on pj_sock_type
  */
 const pj_uint16_t PJ_SOCK_STREAM	= SOCK_STREAM;
@@ -347,5 +347,5 @@
     PJ_CHECK_STACK();
 
-    PJ_ASSERT_RETURN(addr && len > 0, PJ_EINVAL);
+    PJ_ASSERT_RETURN(addr && len >= sizeof(struct sockaddr_in), PJ_EINVAL);
 
     if (bind(sock, (struct sockaddr*)addr, len) != 0)
Index: /pjproject/trunk/pjlib/src/pjlib-test/ioq_tcp.c
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/ioq_tcp.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pjlib-test/ioq_tcp.c	(revision 433)
@@ -344,4 +344,11 @@
             }
 
+	    if (status > pending_op) {
+		PJ_LOG(3,(THIS_FILE,
+			  "...error: pj_ioqueue_poll() returned %d "
+			  "(only expecting %d)",
+			  status, pending_op));
+		return -52;
+	    }
 	    pending_op -= status;
 
@@ -479,4 +486,12 @@
 	    }
 
+	    if (status > pending_op) {
+		PJ_LOG(3,(THIS_FILE,
+			  "...error: pj_ioqueue_poll() returned %d "
+			  "(only expecting %d)",
+			  status, pending_op));
+		return -552;
+	    }
+
 	    pending_op -= status;
 	    if (pending_op == 0) {
Index: /pjproject/trunk/pjlib/src/pjlib-test/ioq_udp.c
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/ioq_udp.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pjlib-test/ioq_udp.c	(revision 433)
@@ -42,4 +42,5 @@
 #define PORT		    51233
 #define LOOP		    100
+///#define LOOP		    2
 #define BUF_MIN_SIZE	    32
 #define BUF_MAX_SIZE	    2048
@@ -50,4 +51,11 @@
 #undef TRACE_
 #define TRACE_(msg)	    PJ_LOG(3,(THIS_FILE,"....." msg))
+
+#if 0
+#  define TRACE__(args)	    PJ_LOG(3,args)
+#else
+#  define TRACE__(args)
+#endif
+
 
 static pj_ssize_t            callback_read_size,
@@ -70,4 +78,6 @@
     callback_read_op = op_key;
     callback_read_size = bytes_read;
+    TRACE__((THIS_FILE, "     callback_read_key = %p, bytes=%d", 
+	     key, bytes_read));
 }
 
@@ -255,5 +265,5 @@
 	    status=-45; goto on_error;
         } else if (rc < 0) {
-            app_perror("...ERROR in ioqueue_poll()", rc);
+            app_perror("...ERROR in ioqueue_poll()", -rc);
 	    status=-50; goto on_error;
 	}
@@ -493,5 +503,5 @@
     pj_ioqueue_key_t **key;
     pj_status_t rc;
-    int count, i;
+    int count, i; /* must be signed */
 
     PJ_LOG(3,(THIS_FILE,"...testing with so many handles"));
@@ -534,5 +544,17 @@
     /* Now deregister and close all handles. */ 
 
-    for (i=0; i<count; ++i) {
+    /* NOTE for RTEMS:
+     *  It seems that the order of close(sock) is pretty important here.
+     *  If we close the sockets with the same order as when they were created,
+     *  RTEMS doesn't seem to reuse the sockets, thus next socket created
+     *  will have descriptor higher than the last socket created.
+     *  If we close the sockets in the reverse order, then the descriptor will
+     *  get reused.
+     *  This used to cause problem with select ioqueue, since the ioqueue
+     *  always gives FD_SETSIZE for the first select() argument. This ioqueue
+     *  behavior can be changed with setting PJ_SELECT_NEEDS_NFDS macro.
+     */
+    for (i=count-1; i>=0; --i) {
+    ///for (i=0; i<count; ++i) {
 	rc = pj_ioqueue_unregister(key[i]);
 	if (rc != PJ_SUCCESS) {
@@ -571,7 +593,9 @@
     pj_ioqueue_key_t *skey, *ckey, *key;
     pj_timestamp t1, t2, t_elapsed;
-    int rc=0, i;
+    int rc=0, i;    /* i must be signed */
     pj_str_t temp;
-    char errbuf[128];
+    char errbuf[PJ_ERR_MSG_SIZE];
+
+    TRACE__((THIS_FILE, "   bench test %d", inactive_sock_count));
 
     // Create pool.
@@ -692,6 +716,12 @@
 			       &addr, sizeof(addr));
 	if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
-	    app_perror("...error: pj_ioqueue_write()", bytes);
+	    app_perror("...error: pj_ioqueue_write()", rc);
 	    break;
+	}
+	if (rc == PJ_SUCCESS) {
+	    if (bytes < 0) {
+		app_perror("...error: pj_ioqueue_sendto()", -bytes);
+		break;
+	    }
 	}
 
@@ -702,6 +732,9 @@
         callback_read_key = NULL;
         callback_read_size = 0;
+	TRACE__((THIS_FILE, "     waiting for key = %p", skey));
 	do {
-	    rc = pj_ioqueue_poll(ioque, NULL);
+	    pj_time_val timeout = { 1, 0 };
+	    rc = pj_ioqueue_poll(ioque, &timeout);
+	    TRACE__((THIS_FILE, "     poll rc=%d", rc));
 	} while (rc >= 0 && callback_read_key != skey);
 
@@ -750,8 +783,11 @@
 
     // Cleaning up.
-    for (i=0; i<inactive_sock_count; ++i)
+    for (i=inactive_sock_count-1; i>=0; --i) {
 	pj_sock_close(inactive_sock[i]);
+    }
+
     pj_sock_close(ssock);
     pj_sock_close(csock);
+
 
     pj_ioqueue_destroy(ioque);
Index: /pjproject/trunk/pjlib/src/pjlib-test/main_rtems.c
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/main_rtems.c	(revision 433)
+++ /pjproject/trunk/pjlib/src/pjlib-test/main_rtems.c	(revision 433)
@@ -0,0 +1,325 @@
+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+/*
+ * - Many thanks for Zetron, Inc. and Phil Torre <ptorre@zetron.com> for 
+ *   donating this file and the RTEMS port in general!
+ */
+
+#include "test.h"
+
+#include <pj/errno.h>
+#include <pj/string.h>
+#include <pj/sock.h>
+#include <pj/log.h>
+
+extern int param_echo_sock_type;
+extern const char *param_echo_server;
+extern int param_echo_port;
+
+#include <bsp.h>
+
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS    300
+#define CONFIGURE_MAXIMUM_TASKS                     50
+#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES            rtems_resource_unlimited(10)
+#define CONFIGURE_MAXIMUM_SEMAPHORES                rtems_resource_unlimited(10)
+#define CONFIGURE_MAXIMUM_TIMERS                    50
+#define CONFIGURE_MAXIMUM_REGIONS                   3
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER
+#define CONFIGURE_TICKS_PER_TIMESLICE               2
+//#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+
+#define CONFIGURE_MAXIMUM_POSIX_MUTEXES	    rtems_resource_unlimited(16)
+#define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES rtems_resource_unlimited(5)
+#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES  rtems_resource_unlimited(16)
+#define CONFIGURE_MAXIMUM_POSIX_TIMERS	    rtems_resource_unlimited(5)
+#define CONFIGURE_MAXIMUM_POSIX_THREADS	    rtems_resource_unlimited(16)
+#define CONFIGURE_MAXIMUM_POSIX_KEYS	    rtems_resource_unlimited(16)
+
+#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE	4096
+
+/* Make sure that stack size is at least 4096 */
+#define SZ					(4096-RTEMS_MINIMUM_STACK_SIZE)
+#define CONFIGURE_EXTRA_TASK_STACKS		((SZ)<0 ? 0 : (SZ))
+
+#define CONFIGURE_INIT
+#define STACK_CHECKER_ON
+
+rtems_task Init(rtems_task_argument Argument) ;
+void *POSIX_Init(void *argument);
+
+#include <confdefs.h>
+#include <rtems.h>
+
+/* Any tests that want to build a linked executable for RTEMS must include
+   these headers to get a default config for the network stack. */
+#include <rtems/rtems_bsdnet.h>
+#include "rtems_network_config.h"
+
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define THIS_FILE   "main_rtems.c"
+
+static void* pjlib_test_main(void* unused);
+static void  initialize_network();
+static void test_sock(void);
+
+static void my_perror(pj_status_t status, const char *title)
+{
+    char err[PJ_ERR_MSG_SIZE];
+
+    pj_strerror(status, err, sizeof(err));
+    printf("%s: %s [%d]\n", title, err, status);
+}
+
+#define TEST(expr)    { int rc;\
+		        /*PJ_LOG(3,(THIS_FILE,"%s", #expr));*/ \
+			/*sleep(1);*/ \
+		        rc=expr; \
+		        if (rc) my_perror(PJ_STATUS_FROM_OS(rc),#expr); }
+
+
+
+//rtems_task Init(rtems_task_argument Argument)
+void *POSIX_Init(void *argument)
+{
+    pthread_attr_t	threadAttr;
+    pthread_t     	theThread;
+    struct sched_param	sched_param;
+    size_t		stack_size;
+    int           	result;
+    char		data[1000];
+    
+
+    memset(data, 1, sizeof(data));
+
+    /* Set the TOD clock, so that gettimeofday() will work */
+    rtems_time_of_day fakeTime = { 2006, 3, 15, 17, 30, 0, 0 };
+
+    if (RTEMS_SUCCESSFUL != rtems_clock_set(&fakeTime))
+    {
+	assert(0);
+    }	
+
+    /* Bring up the network stack so we can run the socket tests. */
+    initialize_network();
+
+    /* Start a POSIX thread for pjlib_test_main(), since that's what it
+     * thinks it is running in. 
+     */
+
+    /* Initialize attribute */
+    TEST( pthread_attr_init(&threadAttr) );
+
+    /* Looks like the rest of the attributes must be fully initialized too,
+     * or otherwise pthread_create will return EINVAL.
+     */
+
+    /* Specify explicit scheduling request */
+    TEST( pthread_attr_setinheritsched(&threadAttr, PTHREAD_EXPLICIT_SCHED));
+
+    /* Timeslicing is needed by thread test, and this is accomplished by
+     * SCHED_RR.
+     */
+    TEST( pthread_attr_setschedpolicy(&threadAttr, SCHED_RR));
+
+    /* Set priority */
+    TEST( pthread_attr_getschedparam(&threadAttr, &sched_param));
+    sched_param.sched_priority = NETWORK_STACK_PRIORITY - 10;
+    TEST( pthread_attr_setschedparam(&threadAttr, &sched_param));
+
+    /* Must have sufficient stack size (large size is needed by
+     * logger, because default settings for logger is to use message buffer
+     * from the stack).
+     */
+    TEST( pthread_attr_getstacksize(&threadAttr, &stack_size));
+    if (stack_size < 8192)
+	TEST( pthread_attr_setstacksize(&threadAttr, 8192));
+
+
+    /* Create the thread for application */
+    result = pthread_create(&theThread, &threadAttr, &pjlib_test_main, NULL);
+    if (result != 0) {
+	my_perror(PJ_STATUS_FROM_OS(result), 
+		  "Error creating pjlib_test_main thread");
+	assert(!"Error creating main thread");
+    } 
+
+    return NULL;
+}
+
+
+
+#define boost()
+#define init_signals()
+
+static void*
+pjlib_test_main(void* unused)
+{
+    int rc;
+
+    /* Drop our priority to below that of the network stack, otherwise
+     * select() tests will fail. */
+    struct sched_param schedParam;
+    int schedPolicy;
+  
+    printf("pjlib_test_main thread started..\n");
+
+    TEST( pthread_getschedparam(pthread_self(), &schedPolicy, &schedParam) );
+
+    schedParam.sched_priority = NETWORK_STACK_PRIORITY - 10;
+
+    TEST( pthread_setschedparam(pthread_self(), schedPolicy, &schedParam) );
+
+    boost();
+    init_signals();
+
+    //my_test_thread("from pjlib_test_main");
+    //test_sock();
+
+    rc = test_main();
+
+    return (void*)rc;
+}
+
+#  include <sys/types.h>
+#  include <sys/socket.h>
+#  include <netinet/in.h>
+#  include <arpa/inet.h>
+#  include <unistd.h>
+
+/* 
+ * Send UDP packet to some host. We can then use Ethereal to sniff the packet
+ * to see if this target really transmits UDP packet.
+ */
+static void
+send_udp(const char *target)
+{
+    int sock, rc;
+    struct sockaddr_in addr;
+
+    PJ_LOG(3,("main_rtems.c", "IP addr=%s/%s, gw=%s",
+		DEFAULT_IP_ADDRESS_STRING,
+		DEFAULT_NETMASK_STRING,
+		DEFAULT_GATEWAY_STRING));
+
+    sock = socket(AF_INET, SOCK_DGRAM, 0);
+    assert(sock > 0);
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+
+    rc = bind(sock, (struct sockaddr*)&addr, sizeof(addr));
+    assert("bind error" && rc==0);
+
+    addr.sin_addr.s_addr = inet_addr(target);
+    addr.sin_port = htons(4444);
+
+    while(1) {
+	const char *data = "hello";
+
+	rc = sendto(sock, data, 5, 0, (struct sockaddr*)&addr, sizeof(addr));
+	PJ_LOG(3,("main_rtems.c", "pinging %s..(rc=%d)", target, rc));
+    	sleep(1);
+    }
+}
+
+
+static void test_sock(void)
+{
+    int sock;
+    struct sockaddr_in addr;
+    int rc;
+
+    sock = socket(AF_INET, SOCK_DGRAM, 0);
+    if (sock < 0) {
+	printf("socket() error\n");
+	goto end;
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+    addr.sin_port = htons(5000);
+
+    rc = bind(sock, (struct sockaddr*)&addr, sizeof(addr));
+    if (rc != 0) {
+	printf("bind() error %d\n", rc);
+	close(sock);
+	goto end;
+    }
+
+    puts("Bind socket success");
+
+    close(sock);
+
+end:
+    while(1) sleep(1);
+}
+
+/* 
+ * Initialize the network stack and Ethernet driver, using the configuration
+ * in rtems-network-config.h
+ */
+static void
+initialize_network()
+{
+    unsigned32 fd, result;
+    char ip_address_string[] = DEFAULT_IP_ADDRESS_STRING;
+    char netmask_string[] = DEFAULT_NETMASK_STRING;
+    char gateway_string[] = DEFAULT_GATEWAY_STRING;
+
+    // Write the network config files to /etc/hosts and /etc/host.conf
+    result = mkdir("/etc", S_IRWXU | S_IRWXG | S_IRWXO);
+    fd = open("/etc/host.conf", O_RDWR | O_CREAT, 0744);
+    result = write(fd, "hosts,bind\n", 11);
+    result = close(fd);
+    fd = open("/etc/hosts", O_RDWR | O_CREAT, 0744);
+    result = write(fd, "127.0.0.1	localhost\n", 41);
+    result = write(fd, ip_address_string, strlen(ip_address_string));
+    result = write(fd, "	pjsip-test\n", 32); 
+    result = close(fd);
+
+    netdriver_config.ip_address = ip_address_string;
+    netdriver_config.ip_netmask = netmask_string;
+    rtems_bsdnet_config.gateway = gateway_string;
+
+    if (0 != rtems_bsdnet_initialize_network())
+	PJ_LOG(3,(THIS_FILE, "Error: Unable to initialize network stack!"));
+    else
+	PJ_LOG(3,(THIS_FILE, "IP addr=%s/%s, gw=%s", 
+			      ip_address_string,
+			      netmask_string,
+			      gateway_string));
+
+    //rtems_rdbg_initialize();
+    //enterRdbg();
+    //send_udp("192.168.0.1");
+    //test_sock();
+}
+
+
Index: /pjproject/trunk/pjlib/src/pjlib-test/pool_perf.c
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/pool_perf.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pjlib-test/pool_perf.c	(revision 433)
@@ -33,7 +33,9 @@
 #define COUNT	    1024
 static unsigned	    sizes[COUNT];
+static char	   *p[COUNT];
 #define MIN_SIZE    4
 #define MAX_SIZE    512
 static unsigned total_size;
+
 
 static int pool_test_pool()
@@ -46,6 +48,10 @@
     for (i=0; i<COUNT; ++i) {
 	char *p;
-	if ( (p=(char*)pj_pool_alloc(pool, sizes[i])) == NULL)
+	if ( (p=(char*)pj_pool_alloc(pool, sizes[i])) == NULL) {
+	    PJ_LOG(3,(THIS_FILE,"   error: pool failed to allocate %d bytes",
+		      sizes[i]));
+	    pj_pool_release(pool);
 	    return -1;
+	}
 	*p = '\0';
     }
@@ -57,11 +63,14 @@
 static int pool_test_malloc_free()
 {
-    char *p[COUNT];
-    int i;
+    int i; /* must be signed */
 
     for (i=0; i<COUNT; ++i) {
 	p[i] = (char*)malloc(sizes[i]);
 	if (!p[i]) {
-	    // Don't care for memory leak in this test
+	    PJ_LOG(3,(THIS_FILE,"   error: malloc failed to allocate %d bytes",
+		      sizes[i]));
+	    --i;
+	    while (i >= 0)
+		free(p[i]), --i;
 	    return -1;
 	}
@@ -83,13 +92,16 @@
     pj_uint32_t best, worst;
 
-    // Initialize sizes.
+    /* Initialize size of chunks to allocate in for the test. */
     for (i=0; i<COUNT; ++i) {
-	sizes[i] = MIN_SIZE + pj_rand() % MAX_SIZE;
+	sizes[i] = MIN_SIZE + (pj_rand() % MAX_SIZE);
 	total_size += sizes[i];
     }
 
+    /* Add some more for pool admin area */
+    total_size += 512;
+
     PJ_LOG(3, (THIS_FILE, "Benchmarking pool.."));
 
-    // Warmup
+    /* Warmup */
     pool_test_pool();
     pool_test_malloc_free();
@@ -118,9 +130,9 @@
     }
 
-    PJ_LOG(4, (THIS_FILE, "..LOOP count:                        %u", LOOP));
-    PJ_LOG(4, (THIS_FILE, "..number of alloc/dealloc per loop:  %u", COUNT));
-    PJ_LOG(4, (THIS_FILE, "..pool allocation/deallocation time: %u", pool_time));
-    PJ_LOG(4, (THIS_FILE, "..malloc/free time:                  %u", malloc_time));
-    PJ_LOG(4, (THIS_FILE, "..pool again, second invocation:     %u", pool_time2));
+    PJ_LOG(4,(THIS_FILE,"..LOOP count:                        %u",LOOP));
+    PJ_LOG(4,(THIS_FILE,"..number of alloc/dealloc per loop:  %u",COUNT));
+    PJ_LOG(4,(THIS_FILE,"..pool allocation/deallocation time: %u",pool_time));
+    PJ_LOG(4,(THIS_FILE,"..malloc/free time:                  %u",malloc_time));
+    PJ_LOG(4,(THIS_FILE,"..pool again, second invocation:     %u",pool_time2));
 
     if (pool_time2==0) pool_time2=1;
@@ -130,5 +142,5 @@
 	best = pool_time2, worst = pool_time;
 
-    PJ_LOG(3, (THIS_FILE, "..malloc Speedup best=%dx, worst=%dx", 
+    PJ_LOG(3, (THIS_FILE, "..pool speedup over malloc best=%dx, worst=%dx", 
 			  (int)(malloc_time/best),
 			  (int)(malloc_time/worst)));
Index: /pjproject/trunk/pjlib/src/pjlib-test/rtems_network_config.h
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/rtems_network_config.h	(revision 433)
+++ /pjproject/trunk/pjlib/src/pjlib-test/rtems_network_config.h	(revision 433)
@@ -0,0 +1,148 @@
+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+/*
+ * Thanks Zetron, Inc and Phil Torre <ptorre@zetron.com> for donating PJLIB
+ * port to RTEMS.
+ */
+
+/*
+ * Network configuration
+ * 
+ ************************************************************
+ * EDIT THIS FILE TO REFLECT YOUR NETWORK CONFIGURATION     *
+ * BEFORE RUNNING ANY RTEMS PROGRAMS WHICH USE THE NETWORK! * 
+ ************************************************************
+ *
+ */
+
+#ifndef _RTEMS_NETWORKCONFIG_H_
+#define _RTEMS_NETWORKCONFIG_H_
+
+
+#define DEFAULT_IP_ADDRESS_STRING "192.168.0.2"
+#define DEFAULT_NETMASK_STRING    "255.255.255.0"
+#define DEFAULT_GATEWAY_STRING    "192.168.0.1"
+
+
+
+
+#ifndef RTEMS_BSP_NETWORK_DRIVER_NAME
+#warning "RTEMS_BSP_NETWORK_DRIVER_NAME is not defined"
+#define RTEMS_BSP_NETWORK_DRIVER_NAME "no_network1"
+#endif
+
+#ifndef RTEMS_BSP_NETWORK_DRIVER_ATTACH
+#warning "RTEMS_BSP_NETWORK_DRIVER_ATTACH is not defined"
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH 0
+#endif
+
+#define NETWORK_STACK_PRIORITY 128
+/* #define RTEMS_USE_BOOTP */
+
+/* #define RTEMS_USE_LOOPBACK */
+
+#include <bsp.h>
+
+/*
+ * Define RTEMS_SET_ETHERNET_ADDRESS if you want to specify the
+ * Ethernet address here.  If RTEMS_SET_ETHERNET_ADDRESS is not
+ * defined the driver will choose an address.
+ */
+// NOTE:  The address below is a dummy address that should only ever
+// be used for testing on a private network.  DO NOT LET A PRODUCT
+// CONTAINING THIS ETHERNET ADDRESS OUT INTO THE FIELD!
+//#define RTEMS_SET_ETHERNET_ADDRESS
+#if (defined (RTEMS_SET_ETHERNET_ADDRESS))
+static char ethernet_address[6] = { 0x00, 0x80, 0x7F, 0x22, 0x61, 0x77 };
+#endif
+
+#define RTEMS_USE_LOOPBACK 
+#ifdef RTEMS_USE_LOOPBACK 
+/*
+ * Loopback interface
+ */
+extern int rtems_bsdnet_loopattach(struct rtems_bsdnet_ifconfig* dummy, int unused);
+static struct rtems_bsdnet_ifconfig loopback_config = {
+	"lo0",				/* name */
+	rtems_bsdnet_loopattach,	/* attach function */
+	NULL,				/* link to next interface */
+	"127.0.0.1",			/* IP address */
+	"255.0.0.0",			/* IP net mask */
+};
+#endif
+
+/*
+ * Default network interface
+ */
+static struct rtems_bsdnet_ifconfig netdriver_config = {
+	RTEMS_BSP_NETWORK_DRIVER_NAME,		/* name */
+	RTEMS_BSP_NETWORK_DRIVER_ATTACH,	/* attach function */
+
+#ifdef RTEMS_USE_LOOPBACK 
+	&loopback_config,		/* link to next interface */
+#else
+	NULL,				/* No more interfaces */
+#endif
+
+#if (defined (RTEMS_USE_BOOTP))
+	NULL,				/* BOOTP supplies IP address */
+	NULL,				/* BOOTP supplies IP net mask */
+#else
+	"192.168.0.33",			/* IP address */
+	"255.255.255.0",		/* IP net mask */
+#endif /* !RTEMS_USE_BOOTP */
+
+#if (defined (RTEMS_SET_ETHERNET_ADDRESS))
+	ethernet_address,               /* Ethernet hardware address */
+#else
+	NULL,                           /* Driver supplies hardware address */
+#endif
+	0				/* Use default driver parameters */
+};
+
+/*
+ * Network configuration
+ */
+struct rtems_bsdnet_config rtems_bsdnet_config = {
+	&netdriver_config,
+
+#if (defined (RTEMS_USE_BOOTP))
+	rtems_bsdnet_do_bootp,
+#else
+	NULL,
+#endif
+
+	NETWORK_STACK_PRIORITY,		/* Default network task priority */
+	1048576,			/* Default mbuf capacity */
+	1048576,			/* Default mbuf cluster capacity */
+
+#if (!defined (RTEMS_USE_BOOTP))
+	"testnode",		/* Host name */
+	"example.org",		/* Domain name */
+	"192.168.6.9",		/* Gateway */
+	"192.168.7.41",		/* Log host */
+	{"198.137.231.1" },	/* Name server(s) */
+	{"207.202.190.162" },	/* NTP server(s) */
+#endif /* !RTEMS_USE_BOOTP */
+
+};
+
+#endif	/* _RTEMS_NETWORKCONFIG_H_ */
+
Index: /pjproject/trunk/pjlib/src/pjlib-test/sock.c
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/sock.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pjlib-test/sock.c	(revision 433)
@@ -64,4 +64,10 @@
 #define TCP_PORT        (UDP_PORT+10)
 #define BIG_DATA_LEN	9000
+#define ADDRESS		"127.0.0.1"
+#define A0		127
+#define A1		0
+#define A2		0
+#define A3		1
+
 
 static char bigdata[BIG_DATA_LEN];
@@ -70,6 +76,6 @@
 static int format_test(void)
 {
-    pj_str_t s = pj_str("127.0.0.1");
-    char *p;
+    pj_str_t s = pj_str(ADDRESS);
+    unsigned char *p;
     pj_in_addr addr;
     const pj_str_t *hostname;
@@ -82,7 +88,11 @@
     
     /* Check the result. */
-    p = (char*)&addr;
-    if (p[0]!=127 || p[1]!=0 || p[2]!=0 || p[3]!=1)
+    p = (unsigned char*)&addr;
+    if (p[0]!=A0 || p[1]!=A1 || p[2]!=A2 || p[3]!=A3) {
+	PJ_LOG(3,("test", "  error: mismatched address. p0=%d, p1=%d, "
+			  "p2=%d, p3=%d", p[0] & 0xFF, p[1] & 0xFF, 
+			   p[2] & 0xFF, p[3] & 0xFF));
 	return -15;
+    }
 
     /* pj_inet_ntoa() */
@@ -98,4 +108,7 @@
     if (!hostname || !hostname->ptr || !hostname->slen)
 	return -40;
+
+    PJ_LOG(3,("test", "....hostname is %.*s", 
+	      (int)hostname->slen, hostname->ptr));
 
     /* pj_gethostaddr() */
@@ -314,8 +327,8 @@
     dstaddr.sin_family = PJ_AF_INET;
     dstaddr.sin_port = pj_htons(UDP_PORT);
-    dstaddr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));
+    dstaddr.sin_addr = pj_inet_addr(pj_cstr(&s, ADDRESS));
     
     if ((rc=pj_sock_bind(ss, &dstaddr, sizeof(dstaddr))) != 0) {
-	app_perror("...bind error", rc);
+	app_perror("...bind error udp:"ADDRESS, rc);
 	rc = -120; goto on_error;
     }
@@ -325,5 +338,5 @@
     srcaddr.sin_family = PJ_AF_INET;
     srcaddr.sin_port = pj_htons(UDP_PORT-1);
-    srcaddr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));
+    srcaddr.sin_addr = pj_inet_addr(pj_cstr(&s, ADDRESS));
 
     if ((rc=pj_sock_bind(cs, &srcaddr, sizeof(srcaddr))) != 0) {
Index: /pjproject/trunk/pjlib/src/pjlib-test/test.c
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/test.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pjlib-test/test.c	(revision 433)
@@ -41,4 +41,9 @@
 		      PJ_LOG_HAS_MICRO_SEC;
 
+int null_func()
+{
+    return 0;
+}
+
 int test_inner(void)
 {
@@ -59,13 +64,9 @@
     }
     
-    pj_dump_config();
+    //pj_dump_config();
     pj_caching_pool_init( &caching_pool, &pj_pool_factory_default_policy, 0 );
 
 #if INCLUDE_ERRNO_TEST
     DO_TEST( errno_test() );
-#endif
-
-#if INCLUDE_TIMESTAMP_TEST
-    DO_TEST( timestamp_test() );
 #endif
 
@@ -100,4 +101,8 @@
 #if INCLUDE_RBTREE_TEST
     DO_TEST( rbtree_test() );
+#endif
+
+#if INCLUDE_TIMESTAMP_TEST
+    DO_TEST( timestamp_test() );
 #endif
 
Index: /pjproject/trunk/pjlib/src/pjlib-test/test.h
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/test.h	(revision 432)
+++ /pjproject/trunk/pjlib/src/pjlib-test/test.h	(revision 433)
@@ -22,9 +22,9 @@
 #include <pj/types.h>
 
-#define GROUP_LIBC                  1
-#define GROUP_OS                    1
-#define GROUP_DATA_STRUCTURE        1
-#define GROUP_NETWORK               1
-#define GROUP_FILE                  1
+#define GROUP_LIBC                  0
+#define GROUP_OS                    0
+#define GROUP_DATA_STRUCTURE        0
+#define GROUP_NETWORK               0
+#define GROUP_FILE                  0
 
 #define INCLUDE_ERRNO_TEST          GROUP_LIBC
@@ -49,5 +49,5 @@
 #define INCLUDE_TCP_IOQUEUE_TEST    GROUP_NETWORK
 #define INCLUDE_IOQUEUE_PERF_TEST   GROUP_NETWORK
-#define INCLUDE_IOQUEUE_UNREG_TEST  GROUP_NETWORK
+#define INCLUDE_IOQUEUE_UNREG_TEST  1	// GROUP_NETWORK
 #define INCLUDE_FILE_TEST           GROUP_FILE
 
@@ -104,7 +104,9 @@
 extern pj_status_t  app_socketpair(int family, int type, int protocol,
                                    pj_sock_t *server, pj_sock_t *client);
+extern int	    null_func(void);
 
 //#define TRACE_(expr) PJ_LOG(3,expr)
 #define TRACE_(expr)
+#define HALT(msg)   { PJ_LOG(3,(THIS_FILE,"%s halted",msg)); for(;;) sleep(1); }
 
 PJ_END_DECL
Index: /pjproject/trunk/pjlib/src/pjlib-test/thread.c
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/thread.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pjlib-test/thread.c	(revision 433)
@@ -53,5 +53,12 @@
 #define THIS_FILE   "thread_test"
 
-static int quit_flag=0;
+static volatile int quit_flag=0;
+
+#if 0
+#   define TRACE__(args)	PJ_LOG(3,args)
+#else
+#   define TRACE__(args)
+#endif
+
 
 /*
@@ -66,5 +73,8 @@
     pj_thread_desc desc;
     pj_thread_t *this_thread;
+    unsigned id = *pcounter;
     pj_status_t rc;
+
+    TRACE__((THIS_FILE, "     thread %d running..", id));
 
     rc = pj_thread_register("thread", desc, &this_thread);
@@ -91,7 +101,8 @@
 	(*pcounter)++;
         //Must sleep if platform doesn't do time-slicing.
-	pj_thread_sleep(0);
-    }
-
+	//pj_thread_sleep(0);
+    }
+
+    TRACE__((THIS_FILE, "     thread %d quitting..", id));
     return NULL;
 }
@@ -115,4 +126,5 @@
     quit_flag = 0;
 
+    TRACE__((THIS_FILE, "    Creating thread 0.."));
     rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc,
 			  &counter,
@@ -126,5 +138,7 @@
     }
 
-    pj_thread_sleep(500);
+    TRACE__((THIS_FILE, "    Main thread waiting.."));
+    pj_thread_sleep(1500);
+    TRACE__((THIS_FILE, "    Main thread resuming.."));
 
     if (flags & PJ_THREAD_SUSPENDED) {
@@ -145,5 +159,5 @@
     PJ_LOG(3,(THIS_FILE, "..waiting for thread to quit.."));
 
-    pj_thread_sleep(500);
+    pj_thread_sleep(1500);
 
     quit_flag = 1;
@@ -176,5 +190,5 @@
     quit_flag = 0;
 
-    pool = pj_pool_create(mem, NULL, 4096, 0, NULL);
+    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
     if (!pool)
         return -10;
@@ -184,5 +198,5 @@
     /* Create all threads in suspended mode. */
     for (i=0; i<NUM_THREADS; ++i) {
-        counter[i] = 0;
+        counter[i] = i;
         rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc, 
 			      &counter[i], 
@@ -199,9 +213,11 @@
      * The purpose of this is to test whether all threads are suspended.
      */
+    TRACE__((THIS_FILE, "    Main thread waiting.."));
     pj_thread_sleep(1000);
+    TRACE__((THIS_FILE, "    Main thread resuming.."));
 
     /* Check that all counters are still zero. */
     for (i=0; i<NUM_THREADS; ++i) {
-        if (counter[i] != 0) {
+        if (counter[i] > i) {
             PJ_LOG(3,(THIS_FILE, "....ERROR! Thread %d-th is not suspended!", 
 		      i));
@@ -212,4 +228,5 @@
     /* Now resume all threads. */
     for (i=0; i<NUM_THREADS; ++i) {
+	TRACE__((THIS_FILE, "    Resuming thread %d [%p]..", i, thread[i]));
         rc = pj_thread_resume(thread[i]);
         if (rc != PJ_SUCCESS) {
@@ -223,5 +240,7 @@
      * but it'll make user waits for longer for the test to finish.
      */
+    TRACE__((THIS_FILE, "    Main thread waiting (5s).."));
     pj_thread_sleep(5000);
+    TRACE__((THIS_FILE, "    Main thread resuming.."));
 
     /* Signal all threads to quit. */
@@ -230,4 +249,6 @@
     /* Wait until all threads quit, then destroy. */
     for (i=0; i<NUM_THREADS; ++i) {
+	TRACE__((THIS_FILE, "    Main thread joining thread %d [%p]..", 
+			    i, thread[i]));
         rc = pj_thread_join(thread[i]);
         if (rc != PJ_SUCCESS) {
@@ -235,4 +256,5 @@
             return -50;
         }
+	TRACE__((THIS_FILE, "    Destroying thread %d [%p]..", i, thread[i]));
         rc = pj_thread_destroy(thread[i]);
         if (rc != PJ_SUCCESS) {
@@ -241,4 +263,6 @@
         }
     }
+
+    TRACE__((THIS_FILE, "    Main thread calculating time slices.."));
 
     /* Now examine the value of the counters.
@@ -264,7 +288,9 @@
     diff = (highest-lowest)*100 / ((highest+lowest)/2);
     if ( diff >= 50) {
-        PJ_LOG(3,(THIS_FILE, "...ERROR: thread didn't have equal timeslice!"));
-        PJ_LOG(3,(THIS_FILE, ".....lowest counter=%u, highest counter=%u, diff=%u%%",
-                             lowest, highest, diff));
+        PJ_LOG(3,(THIS_FILE, 
+		  "...ERROR: thread didn't have equal timeslice!"));
+        PJ_LOG(3,(THIS_FILE, 
+		  ".....lowest counter=%u, highest counter=%u, diff=%u%%",
+                  lowest, highest, diff));
         return -80;
     } else {
@@ -274,4 +300,5 @@
     }
 
+    pj_pool_release(pool);
     return 0;
 }
Index: /pjproject/trunk/pjlib/src/pjlib-test/timestamp.c
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/timestamp.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pjlib-test/timestamp.c	(revision 433)
@@ -189,6 +189,12 @@
 
     /* Loop.. */
-    for (i=0; i<1000000; ++i)
-	;
+    for (i=0; i<1000000; ++i) {
+	/* Try to do something so that smart compilers wont
+	 * remove this silly loop.
+	 */
+	null_func();
+    }
+
+    sleep(0);
 
     /* Mark end time. */
@@ -199,6 +205,8 @@
     PJ_LOG(3,(THIS_FILE, "....elapsed: %u usec", (unsigned)elapsed));
 
-    /* See if elapsed time is reasonable. */
-    if (elapsed < 1 || elapsed > 100000) {
+    /* See if elapsed time is "reasonable". 
+     * This should be good even on 50Mhz embedded powerpc.
+     */
+    if (elapsed < 1 || elapsed > 1000000) {
 	PJ_LOG(3,(THIS_FILE, "....error: elapsed time outside window (%u, "
 			     "t1.u32.hi=%u, t1.u32.lo=%u, "
Index: /pjproject/trunk/pjlib/src/pjlib-test/util.c
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/util.c	(revision 432)
+++ /pjproject/trunk/pjlib/src/pjlib-test/util.c	(revision 433)
@@ -20,12 +20,14 @@
 #include <pjlib.h>
 
+#define THIS_FILE "util.c"
+
 void app_perror(const char *msg, pj_status_t rc)
 {
-    char errbuf[256];
+    char errbuf[PJ_ERR_MSG_SIZE];
 
     PJ_CHECK_STACK();
 
     pj_strerror(rc, errbuf, sizeof(errbuf));
-    PJ_LOG(1,("test", "%s: [pj_status_t=%d] %s", msg, rc, errbuf));
+    PJ_LOG(3,("test", "%s: [pj_status_t=%d] %s", msg, rc, errbuf));
 }
 
Index: /pjproject/trunk/pjmedia/build/os-rtems.mak
===================================================================
--- /pjproject/trunk/pjmedia/build/os-rtems.mak	(revision 433)
+++ /pjproject/trunk/pjmedia/build/os-rtems.mak	(revision 433)
@@ -0,0 +1,7 @@
+#
+# PJMEDIA OS specific configuration for RTEMS OS target.
+#
+
+export PJMEDIA_OBJS += nullsound.o
+export SOUND_OBJS = $(NULLSOUND_OBJS)
+
Index: /pjproject/trunk/pjmedia/src/pjmedia-codec/gsm/config.h
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-codec/gsm/config.h	(revision 432)
+++ /pjproject/trunk/pjmedia/src/pjmedia-codec/gsm/config.h	(revision 433)
@@ -10,29 +10,30 @@
 #define	CONFIG_H
 
-/*efine	SIGHANDLER_T	int 		// * signal handlers are void	*/
-/*efine HAS_SYSV_SIGNAL	1		// * sigs not blocked/reset?	*/
+//#define   SIGHANDLER_T	int	// * signal handlers are void	*/
+//#define   HAS_SYSV_SIGNAL	1	// * sigs not blocked/reset?	*/
 
-#define	HAS_STDLIB_H	1		/* /usr/include/stdlib.h	*/
-/*efine	HAS_LIMITS_H	1		// * /usr/include/limits.h	*/
-#define	HAS_FCNTL_H	1		/* /usr/include/fcntl.h		*/
-/*efine	HAS_ERRNO_DECL	1		// * errno.h declares errno	*/
+#define	    HAS_STDLIB_H	1	/* /usr/include/stdlib.h	*/
+//#define   HAS_LIMITS_H	1	// * /usr/include/limits.h	*/
+#define	    HAS_FCNTL_H		1	/* /usr/include/fcntl.h		*/
+//#define   HAS_ERRNO_DECL	1	// * errno.h declares errno	*/
 
-#define	HAS_FSTAT 	1		/* fstat syscall		*/
-#define	HAS_FCHMOD 	1		/* fchmod syscall		*/
-#define	HAS_CHMOD 	1		/* chmod syscall		*/
-#define	HAS_FCHOWN 	1		/* fchown syscall		*/
-#define	HAS_CHOWN 	1		/* chown syscall		*/
-/*efine	HAS__FSETMODE 	1		// * _fsetmode -- set file mode	*/
+#define	    HAS_FSTAT		1	/* fstat syscall		*/
+#define	    HAS_FCHMOD		1	/* fchmod syscall		*/
+#define	    HAS_CHMOD		1	/* chmod syscall		*/
+#define	    HAS_FCHOWN		1	/* fchown syscall		*/
+#define	    HAS_CHOWN		1	/* chown syscall		*/
+//#define   HAS__FSETMODE 	1	// * _fsetmode -- set file mode	*/
 
-#define	HAS_STRING_H 	1		/* /usr/include/string.h 	*/
-/*efine	HAS_STRINGS_H	1		// * /usr/include/strings.h 	*/
+#define	    HAS_STRING_H 	1	/* /usr/include/string.h 	*/
+//#define   HAS_STRINGS_H	1	// * /usr/include/strings.h 	*/
 
-#define	HAS_UNISTD_H	1		/* /usr/include/unistd.h	*/
-#define	HAS_UTIME	1		/* POSIX utime(path, times)	*/
-/*efine	HAS_UTIMES	1		// * use utimes()	syscall instead	*/
-#define	HAS_UTIME_H	1		/* UTIME header file		*/
-/*efine	HAS_UTIMBUF	1		// * struct utimbuf		*/
-/*efine	HAS_UTIMEUSEC   1		// * microseconds in utimbuf?	*/
+#define	    HAS_UNISTD_H	1	/* /usr/include/unistd.h	*/
+#define	    HAS_UTIME		1	/* POSIX utime(path, times)	*/
+//#define   HAS_UTIMES		1	// * use utimes() syscall instead*/
+#define	    HAS_UTIME_H		1	/* UTIME header file		*/
+//#define   HAS_UTIMBUF		1	// * struct utimbuf		*/
+//#define   HAS_UTIMEUSEC	1	// * microseconds in utimbuf?	*/
 
 
 #endif	/* CONFIG_H */
+
Index: /pjproject/trunk/pjmedia/src/test/main.c
===================================================================
--- /pjproject/trunk/pjmedia/src/test/main.c	(revision 432)
+++ /pjproject/trunk/pjmedia/src/test/main.c	(revision 433)
@@ -19,4 +19,15 @@
 #include "test.h"
 
+ 
+/* Any tests that want to build a linked executable for RTEMS must include
+   this header to get a default config for the network stack. */
+#if defined(PJ_RTEMS) 
+#   include <bsp.h>
+#   include <rtems.h>
+#   include <rtems/rtems_bsdnet.h>
+#   include "../../../pjlib/include/rtems-network-config.h"
+#endif
+
+
 int main()
 {
