diff --git a/README-configure b/README-configure new file mode 100644 index 000000000..790848f05 --- /dev/null +++ b/README-configure @@ -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. + diff --git a/build.mak.txt b/build.mak.txt deleted file mode 100644 index 656d2b4ff..000000000 --- a/build.mak.txt +++ /dev/null @@ -1,72 +0,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 - diff --git a/build/cc-gcc.mak b/build/cc-gcc.mak index 9a5ff2f6a..a3b4807e7 100644 --- a/build/cc-gcc.mak +++ b/build/cc-gcc.mak @@ -1,5 +1,5 @@ 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 export RANLIB = $(CROSS_COMPILE)ranlib diff --git a/build/host-unix.mak b/build/host-unix.mak index a84f3ec10..18dcfd5e7 100644 --- a/build/host-unix.mak +++ b/build/host-unix.mak @@ -2,7 +2,7 @@ export HOST_MV := mv export HOST_RM := rm -f @@ 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 := / diff --git a/build/m-mpc860.mak b/build/m-mpc860.mak new file mode 100644 index 000000000..04ff94711 --- /dev/null +++ b/build/m-mpc860.mak @@ -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 := + diff --git a/build/os-rtems.mak b/build/os-rtems.mak new file mode 100644 index 000000000..787294020 --- /dev/null +++ b/build/os-rtems.mak @@ -0,0 +1,17 @@ +# +# Global OS specific configurations for RTEMS OS. +# +# Thanks Zetron, Inc and Phil Torre 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 := + diff --git a/build/rules.mak b/build/rules.mak index 81ef8ce96..6a25b17b9 100644 --- a/build/rules.mak +++ b/build/rules.mak @@ -154,7 +154,7 @@ depend: for F in $(FULL_SRCS); do \ 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 \ echo 'err:' >> $(DEP_FILE); \ diff --git a/configure b/configure index 63bd40965..408ef7fe1 100755 --- a/configure +++ b/configure @@ -1,14 +1,13 @@ #!/bin/sh # -# 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 MACHINE_NAME=i386 @@ -17,14 +16,17 @@ elif echo $MACHINE | grep alpha > /dev/null; then elif echo $MACHINE | grep powerpc > /dev/null; then 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 OS_NAME=sunos @@ -53,25 +55,33 @@ elif echo $SYSTEM | grep -i cygwin > /dev/null; then elif echo $SYSTEM | grep -i darwin > /dev/null; then 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')" exit 1 fi # -# 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 if test -f build.mak; then @@ -85,6 +95,7 @@ echo " OS_NAME = $OS_NAME" echo " HOST_NAME = $HOST_NAME" echo " CC_NAME = $CC_NAME" echo " TARGET_NAME = $TARGET_NAME" +echo " CROSS_COMPILE= $CROSS_COMPILE" echo " LINUX_POLL = $LINUX_POLL" echo "# Auto-generated build.mak" > build.mak @@ -93,6 +104,7 @@ echo "export OS_NAME := $OS_NAME" >> build.mak echo "export HOST_NAME := $HOST_NAME" >> build.mak 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 touch user.mak diff --git a/pjlib/build/os-rtems.mak b/pjlib/build/os-rtems.mak new file mode 100644 index 000000000..1501dd9b2 --- /dev/null +++ b/pjlib/build/os-rtems.mak @@ -0,0 +1,46 @@ +# +# PJLIB OS specific configuration for RTEMS +# +# Thanks Zetron, Inc. and Phil Torre 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 + + + diff --git a/pjlib/include/pj/compat/os_darwinos.h b/pjlib/include/pj/compat/os_darwinos.h index 9a0f90b03..e797c438c 100644 --- a/pjlib/include/pj/compat/os_darwinos.h +++ b/pjlib/include/pj/compat/os_darwinos.h @@ -94,6 +94,10 @@ * Socket related */ typedef int socklen_t; + +/* Set 1 if native sockaddr_in has sin_len member. + * Default: 0 + */ #define PJ_SOCKADDR_HAS_LEN 1 /* @@ -105,6 +109,32 @@ typedef int socklen_t; */ #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__ */ diff --git a/pjlib/include/pj/compat/os_linux.h b/pjlib/include/pj/compat/os_linux.h index eb6264ea7..f0bef355e 100644 --- a/pjlib/include/pj/compat/os_linux.h +++ b/pjlib/include/pj/compat/os_linux.h @@ -54,8 +54,24 @@ #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 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? */ #define PJ_HAS_ERRNO_VAR 1 @@ -89,5 +105,21 @@ #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__ */ diff --git a/pjlib/include/pj/compat/os_linux_kernel.h b/pjlib/include/pj/compat/os_linux_kernel.h index e481248df..fe3f737c0 100644 --- a/pjlib/include/pj/compat/os_linux_kernel.h +++ b/pjlib/include/pj/compat/os_linux_kernel.h @@ -54,6 +54,10 @@ #define PJ_HAS_WINSOCK2_H 0 #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 /* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return @@ -61,6 +65,18 @@ */ #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 * socket recv() can not return immediate daata. */ @@ -104,5 +120,21 @@ #define PJ_ATOMIC_VALUE_TYPE int #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__ */ diff --git a/pjlib/include/pj/compat/os_palmos.h b/pjlib/include/pj/compat/os_palmos.h index 478e87156..cdabf00f2 100644 --- a/pjlib/include/pj/compat/os_palmos.h +++ b/pjlib/include/pj/compat/os_palmos.h @@ -52,8 +52,24 @@ #define PJ_HAS_WINSOCK2_H 0 #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? */ #define PJ_HAS_ERRNO_VAR 0 @@ -83,4 +99,20 @@ # define PJ_OS_HAS_CHECK_STACK 0 #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__ */ + diff --git a/pjlib/include/pj/compat/os_rtems.h b/pjlib/include/pj/compat/os_rtems.h new file mode 100644 index 000000000..f764f9be3 --- /dev/null +++ b/pjlib/include/pj/compat/os_rtems.h @@ -0,0 +1,135 @@ +/* $Id$ */ +/* + * Copyright (C)2003-2006 Benny Prijono + * + * 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 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__ */ + diff --git a/pjlib/include/pj/compat/os_sunos.h b/pjlib/include/pj/compat/os_sunos.h index 389d66c29..56c48306e 100644 --- a/pjlib/include/pj/compat/os_sunos.h +++ b/pjlib/include/pj/compat/os_sunos.h @@ -54,6 +54,10 @@ #define PJ_HAS_WINSOCK2_H 0 #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 /* Is errno a good way to retrieve OS errors? @@ -75,6 +79,18 @@ */ #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 # define PJ_HAS_THREADS (1) @@ -92,5 +108,21 @@ /* Get BSD related identifers in Sun's include files */ #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__ */ diff --git a/pjlib/include/pj/compat/os_win32.h b/pjlib/include/pj/compat/os_win32.h index 5abfc89de..cf7431d66 100644 --- a/pjlib/include/pj/compat/os_win32.h +++ b/pjlib/include/pj/compat/os_win32.h @@ -60,6 +60,10 @@ #define PJ_HAS_WINSOCK2_H 1 #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 /* Is errno a good way to retrieve OS errors? (No) @@ -81,6 +85,18 @@ */ #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 # define PJ_HAS_THREADS (1) @@ -95,4 +111,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 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__ */ + diff --git a/pjlib/include/pj/compat/os_win32_wince.h b/pjlib/include/pj/compat/os_win32_wince.h index f6d46e892..36954baec 100644 --- a/pjlib/include/pj/compat/os_win32_wince.h +++ b/pjlib/include/pj/compat/os_win32_wince.h @@ -58,6 +58,10 @@ #define PJ_HAS_WINSOCK2_H 1 #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 /* Is errno a good way to retrieve OS errors? (no) @@ -79,6 +83,18 @@ */ #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 # define PJ_HAS_THREADS (1) @@ -102,5 +118,20 @@ /* Native string is Unicode. */ #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__ */ diff --git a/pjlib/include/pj/config.h b/pjlib/include/pj/config.h index cd95dbcde..1d74d8c70 100644 --- a/pjlib/include/pj/config.h +++ b/pjlib/include/pj/config.h @@ -53,6 +53,8 @@ # include #elif defined(PJ_DARWINOS) && PJ_DARWINOS!=0 # include +#elif defined(PJ_RTEMS) && PJ_RTEMS!=0 +# include #else # error "Please specify target os." #endif @@ -222,6 +224,17 @@ #endif +/** + * 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? * @@ -556,7 +569,17 @@ # error "PJ_IS_BIG_ENDIAN is not defined!" #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 diff --git a/pjlib/include/pj/os.h b/pjlib/include/pj/os.h index 991dacd0c..439b08641 100644 --- a/pjlib/include/pj/os.h +++ b/pjlib/include/pj/os.h @@ -58,12 +58,6 @@ typedef enum pj_thread_create_flags } 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 - /** * Type of thread entry function. */ @@ -161,12 +155,13 @@ PJ_DECL(pj_status_t) pj_thread_resume(pj_thread_t *thread); PJ_DECL(pj_thread_t*) pj_thread_this(void); /** - * 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); diff --git a/pjlib/src/pj/hash.c b/pjlib/src/pj/hash.c index 0495fadc0..1f86317b6 100644 --- a/pjlib/src/pj/hash.c +++ b/pjlib/src/pj/hash.c @@ -49,20 +49,21 @@ struct pj_hash_table_t -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(); if (keylen==PJ_HASH_KEY_STRING) { const unsigned char *p = key; for ( ; *p; ++p ) { - hash = hash * PJ_HASH_MULTIPLIER + *p; + hash = (hash * PJ_HASH_MULTIPLIER) + *p; } } else { const unsigned char *p = key, *end = p + keylen; for ( ; p!=end; ++p) { - hash = hash * PJ_HASH_MULTIPLIER + *p; + hash = (hash * PJ_HASH_MULTIPLIER) + *p; } } return hash; diff --git a/pjlib/src/pj/ioqueue_common_abs.c b/pjlib/src/pj/ioqueue_common_abs.c index b128d810a..60a2b21db 100644 --- a/pjlib/src/pj/ioqueue_common_abs.c +++ b/pjlib/src/pj/ioqueue_common_abs.c @@ -237,7 +237,7 @@ void ioqueue_dispatch_write_event(pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h) socklen_t addrlen = sizeof(addr); gp_rc = getpeername(h->fd, (struct sockaddr*)&addr, &addrlen); - bytes_transfered = gp_rc; + bytes_transfered = (gp_rc < 0) ? gp_rc : -gp_rc; } #endif diff --git a/pjlib/src/pj/ioqueue_select.c b/pjlib/src/pj/ioqueue_select.c index 4aa4f9102..33fcae7d6 100644 --- a/pjlib/src/pj/ioqueue_select.c +++ b/pjlib/src/pj/ioqueue_select.c @@ -93,6 +93,12 @@ PJ_DECL(pj_size_t) PJ_FD_COUNT(const pj_fd_set_t *fdsetp); */ #define VALIDATE_FD_SET 0 +#if 0 +# define TRACE__(args) PJ_LOG(3,args) +#else +# define TRACE__(args) +#endif + /* * This describes each key. */ @@ -108,8 +114,9 @@ struct pj_ioqueue_t { 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; #if PJ_HAS_TCP @@ -136,6 +143,32 @@ PJ_DEF(const char*) pj_ioqueue_name(void) 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 + + /* * pj_ioqueue_create() * @@ -172,6 +205,8 @@ PJ_DEF(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, #endif pj_list_init(&ioqueue->active_list); + rescan_fdset(ioqueue); + #if PJ_IOQUEUE_HAS_SAFE_UNREG /* When safe unregistration is used (the default), we pre-create * all keys and put them in the free list. @@ -332,6 +367,9 @@ PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, pj_list_insert_before(&ioqueue->active_list, key); ++ioqueue->count; + /* Rescan fdset to get max descriptor */ + rescan_fdset(ioqueue); + on_return: /* On error, socket may be left in non-blocking mode. */ *p_key = key; @@ -368,6 +406,8 @@ static void decrement_counter(pj_ioqueue_key_t *key) pj_lock_acquire(key->ioqueue->lock); 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); } pj_mutex_unlock(key->ioqueue->ref_cnt_mutex); @@ -611,6 +651,7 @@ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout) scan_closing_keys(ioqueue); #endif pj_lock_release(ioqueue->lock); + TRACE__((THIS_FILE, " poll: no fd is set")); if (timeout) pj_thread_sleep(PJ_TIME_VAL_MSEC(*timeout)); return 0; @@ -632,7 +673,8 @@ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout) /* Unlock ioqueue before select(). */ 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) return -pj_get_netos_error(); diff --git a/pjlib/src/pj/os_core_unix.c b/pjlib/src/pj/os_core_unix.c index ad9f6143f..d37c142bd 100644 --- a/pjlib/src/pj/os_core_unix.c +++ b/pjlib/src/pj/os_core_unix.c @@ -16,6 +16,11 @@ * along with this program; if not, write to the Free Software * 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 #include @@ -153,7 +158,7 @@ PJ_DEF(pj_status_t) pj_init(void) } #endif - PJ_LOG(4,(THIS_FILE, "pjlib %s for Unix initialized", + PJ_LOG(4,(THIS_FILE, "pjlib %s for POSIX initialized", PJ_VERSION)); return PJ_SUCCESS; @@ -196,6 +201,8 @@ PJ_DEF(pj_status_t) pj_thread_register ( const char *cstr_thread_name, // has been deleted by application. //*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")); } /* Initialize and set the thread entry. */ @@ -281,6 +288,7 @@ static void *thread_main(void *param) /* Done. */ PJ_LOG(6,(rec->obj_name, "Thread quitting")); + return result; } #endif @@ -298,15 +306,18 @@ PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool, { #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(); PJ_ASSERT_RETURN(pool && proc && ptr_thread, PJ_EINVAL); /* 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. */ if (!thread_name) @@ -319,32 +330,61 @@ PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool, rec->obj_name[PJ_MAX_OBJ_NAME-1] = '\0'; } + /* 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 /* Emulate suspended thread with mutex. */ 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); } else { pj_assert(rec->suspended_mutex == NULL); } - 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 pj_assert(!"Threading is disabled!"); @@ -423,8 +463,13 @@ PJ_DEF(pj_status_t) pj_thread_join(pj_thread_t *p) 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 . + */ + return result==ESRCH ? PJ_SUCCESS : PJ_RETURN_OS_ERROR(result); + } #else PJ_CHECK_STACK(); pj_assert(!"No multithreading support!"); @@ -437,10 +482,14 @@ PJ_DEF(pj_status_t) pj_thread_join(pj_thread_t *p) */ 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(); + + /* Destroy mutex used to suspend thread */ + if (p->suspended_mutex) { + pj_mutex_destroy(p->suspended_mutex); + p->suspended_mutex = NULL; + } + return PJ_SUCCESS; } @@ -449,8 +498,26 @@ PJ_DEF(pj_status_t) pj_thread_destroy(pj_thread_t *p) */ PJ_DEF(pj_status_t) pj_thread_sleep(unsigned msec) { +/* 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(); - return usleep(msec * 1000); + 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 */ } #if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0 @@ -513,8 +580,7 @@ PJ_DEF(pj_status_t) pj_atomic_create( pj_pool_t *pool, { 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 rc = pj_mutex_create(pool, "atm%p", PJ_MUTEX_SIMPLE, &atomic_var->mutex); @@ -765,12 +831,16 @@ static pj_status_t init_mutex(pj_mutex_t *mutex, const char *name, int type) 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) { #if defined(PJ_LINUX) && PJ_LINUX!=0 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); #endif @@ -778,6 +848,13 @@ static pj_status_t init_mutex(pj_mutex_t *mutex, const char *name, int type) #if defined(PJ_LINUX) && PJ_LINUX!=0 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 : + // 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); #endif @@ -831,7 +908,7 @@ PJ_DEF(pj_status_t) pj_mutex_create(pj_pool_t *pool, PJ_ASSERT_RETURN(pool && ptr_mutex, PJ_EINVAL); 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) return rc; @@ -1002,6 +1079,13 @@ PJ_DEF(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex) #endif /////////////////////////////////////////////////////////////////////////////// +/* + * 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 { pthread_rwlock_t rwlock; @@ -1095,6 +1179,9 @@ PJ_DEF(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex) return PJ_SUCCESS; } +#endif /* PJ_EMULATE_RWMUTEX */ + + /////////////////////////////////////////////////////////////////////////////// #if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0 @@ -1113,8 +1200,8 @@ PJ_DEF(pj_status_t) pj_sem_create( pj_pool_t *pool, PJ_CHECK_STACK(); 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) return PJ_RETURN_OS_ERROR(pj_get_native_os_error()); diff --git a/pjlib/src/pj/os_rwmutex.c b/pjlib/src/pj/os_rwmutex.c new file mode 100644 index 000000000..2ec147f09 --- /dev/null +++ b/pjlib/src/pj/os_rwmutex.c @@ -0,0 +1,162 @@ +/* $Id$ */ +/* + * Copyright (C)2003-2006 Benny Prijono + * + * 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; +} + diff --git a/pjlib/src/pj/os_time_unix.c b/pjlib/src/pj/os_time_unix.c index b5733b64d..081d97c8e 100644 --- a/pjlib/src/pj/os_time_unix.c +++ b/pjlib/src/pj/os_time_unix.c @@ -17,23 +17,30 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include #if defined(PJ_HAS_UNISTD_H) && PJ_HAS_UNISTD_H!=0 # include #endif +#include + /////////////////////////////////////////////////////////////////////////////// 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; } diff --git a/pjlib/src/pj/os_timestamp_linux.c b/pjlib/src/pj/os_timestamp_posix.c similarity index 100% rename from pjlib/src/pj/os_timestamp_linux.c rename to pjlib/src/pj/os_timestamp_posix.c diff --git a/pjlib/src/pj/pool.c b/pjlib/src/pj/pool.c index e5412d4b8..a9f658c50 100644 --- a/pjlib/src/pj/pool.c +++ b/pjlib/src/pj/pool.c @@ -173,6 +173,11 @@ PJ_DEF(pj_pool_t*) pj_pool_create_int( pj_pool_factory *f, const char *name, 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) return NULL; diff --git a/pjlib/src/pj/sock_bsd.c b/pjlib/src/pj/sock_bsd.c index e207eeaa2..37cb85e58 100644 --- a/pjlib/src/pj/sock_bsd.c +++ b/pjlib/src/pj/sock_bsd.c @@ -26,7 +26,7 @@ /* * 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; const pj_uint16_t PJ_AF_INET = AF_INET; @@ -44,7 +44,7 @@ const pj_uint16_t PJ_AF_IRDA = 0xFFFF; /* * 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; const pj_uint16_t PJ_SOCK_DGRAM = SOCK_DGRAM; @@ -346,7 +346,7 @@ PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sock, { 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) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); diff --git a/pjlib/src/pjlib-test/ioq_tcp.c b/pjlib/src/pjlib-test/ioq_tcp.c index c60d614f0..8f2d74d08 100644 --- a/pjlib/src/pjlib-test/ioq_tcp.c +++ b/pjlib/src/pjlib-test/ioq_tcp.c @@ -343,6 +343,13 @@ static int compliance_test_0(void) callback_connect_status = -2; } + 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; if (pending_op == 0) { @@ -478,6 +485,14 @@ static int compliance_test_1(void) } } + 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) { status = 0; diff --git a/pjlib/src/pjlib-test/ioq_udp.c b/pjlib/src/pjlib-test/ioq_udp.c index 89e2a1e85..7d00690b3 100644 --- a/pjlib/src/pjlib-test/ioq_udp.c +++ b/pjlib/src/pjlib-test/ioq_udp.c @@ -41,6 +41,7 @@ #define THIS_FILE "test_udp" #define PORT 51233 #define LOOP 100 +///#define LOOP 2 #define BUF_MIN_SIZE 32 #define BUF_MAX_SIZE 2048 #define SOCK_INACTIVE_MIN (1) @@ -50,6 +51,13 @@ #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, callback_write_size, callback_accept_status, @@ -69,6 +77,8 @@ static void on_ioqueue_read(pj_ioqueue_key_t *key, callback_read_key = key; callback_read_op = op_key; callback_read_size = bytes_read; + TRACE__((THIS_FILE, " callback_read_key = %p, bytes=%d", + key, bytes_read)); } static void on_ioqueue_write(pj_ioqueue_key_t *key, @@ -254,7 +264,7 @@ static int compliance_test(void) PJ_LOG(1,(THIS_FILE, "...ERROR: timed out...")); 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; } @@ -492,7 +502,7 @@ static int many_handles_test(void) pj_sock_t *sock; 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")); @@ -533,7 +543,19 @@ static int many_handles_test(void) /* Now deregister and close all handles. */ - for (i=0; i=0; --i) { + ///for (i=0; i= 0 && callback_read_key != skey); // End time. @@ -749,11 +782,14 @@ static int bench_test(int bufsize, int inactive_sock_count) } // Cleaning up. - for (i=0; i=0; --i) { pj_sock_close(inactive_sock[i]); + } + pj_sock_close(ssock); pj_sock_close(csock); + pj_ioqueue_destroy(ioque); pj_pool_release( pool); return rc; diff --git a/pjlib/src/pjlib-test/main_rtems.c b/pjlib/src/pjlib-test/main_rtems.c new file mode 100644 index 000000000..963cdc4ec --- /dev/null +++ b/pjlib/src/pjlib-test/main_rtems.c @@ -0,0 +1,325 @@ +/* $Id$ */ +/* + * Copyright (C)2003-2006 Benny Prijono + * + * 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 for + * donating this file and the RTEMS port in general! + */ + +#include "test.h" + +#include +#include +#include +#include + +extern int param_echo_sock_type; +extern const char *param_echo_server; +extern int param_echo_port; + +#include + +#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 +#include + +/* 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 +#include "rtems_network_config.h" + +#include +#include +#include +#include + +#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 +# include +# include +# include +# include + +/* + * 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(); +} + + diff --git a/pjlib/src/pjlib-test/pool_perf.c b/pjlib/src/pjlib-test/pool_perf.c index 6bc6dcfba..077829950 100644 --- a/pjlib/src/pjlib-test/pool_perf.c +++ b/pjlib/src/pjlib-test/pool_perf.c @@ -32,10 +32,12 @@ #define LOOP 10 #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() { int i; @@ -45,8 +47,12 @@ static int pool_test_pool() for (i=0; i= 0) + free(p[i]), --i; return -1; } *p[i] = '\0'; @@ -82,15 +91,18 @@ int pool_perf_test() pj_timestamp start, end; pj_uint32_t best, worst; - // Initialize sizes. + /* Initialize size of chunks to allocate in for the test. */ for (i=0; i + * + * 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 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 + +/* + * 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_ */ + diff --git a/pjlib/src/pjlib-test/sock.c b/pjlib/src/pjlib-test/sock.c index b8af3cd8d..fb6891696 100644 --- a/pjlib/src/pjlib-test/sock.c +++ b/pjlib/src/pjlib-test/sock.c @@ -63,14 +63,20 @@ #define UDP_PORT 51234 #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]; static char bigbuffer[BIG_DATA_LEN]; 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; @@ -81,9 +87,13 @@ static int format_test(void) return -10; /* 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() */ p = pj_inet_ntoa(addr); @@ -98,6 +108,9 @@ static int format_test(void) if (!hostname || !hostname->ptr || !hostname->slen) return -40; + PJ_LOG(3,("test", "....hostname is %.*s", + (int)hostname->slen, hostname->ptr)); + /* pj_gethostaddr() */ return 0; @@ -313,10 +326,10 @@ static int udp_test(void) pj_memset(&dstaddr, 0, sizeof(dstaddr)); 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; } @@ -324,7 +337,7 @@ static int udp_test(void) pj_memset(&srcaddr, 0, sizeof(srcaddr)); 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) { app_perror("...bind error", rc); diff --git a/pjlib/src/pjlib-test/test.c b/pjlib/src/pjlib-test/test.c index 97ba29919..01eeb3c69 100644 --- a/pjlib/src/pjlib-test/test.c +++ b/pjlib/src/pjlib-test/test.c @@ -40,6 +40,11 @@ int param_echo_port = ECHO_SERVER_START_PORT; int param_log_decor = PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC; +int null_func() +{ + return 0; +} + int test_inner(void) { pj_caching_pool caching_pool; @@ -58,17 +63,13 @@ int test_inner(void) return rc; } - 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 - #if INCLUDE_EXCEPTION_TEST DO_TEST( exception_test() ); #endif @@ -101,6 +102,10 @@ int test_inner(void) DO_TEST( rbtree_test() ); #endif +#if INCLUDE_TIMESTAMP_TEST + DO_TEST( timestamp_test() ); +#endif + #if INCLUDE_ATOMIC_TEST DO_TEST( atomic_test() ); #endif diff --git a/pjlib/src/pjlib-test/test.h b/pjlib/src/pjlib-test/test.h index 7a0aeed21..78478df66 100644 --- a/pjlib/src/pjlib-test/test.h +++ b/pjlib/src/pjlib-test/test.h @@ -21,11 +21,11 @@ #include -#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 #define INCLUDE_TIMESTAMP_TEST GROUP_OS @@ -48,7 +48,7 @@ #define INCLUDE_UDP_IOQUEUE_TEST GROUP_NETWORK #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 #define INCLUDE_ECHO_SERVER 0 @@ -103,9 +103,11 @@ extern pj_status_t app_socket(int family, int type, int proto, int port, pj_sock_t *ptr_sock); 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 diff --git a/pjlib/src/pjlib-test/thread.c b/pjlib/src/pjlib-test/thread.c index 72cb2ecd8..866c7698b 100644 --- a/pjlib/src/pjlib-test/thread.c +++ b/pjlib/src/pjlib-test/thread.c @@ -52,7 +52,14 @@ #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 + /* * The thread's entry point. @@ -65,8 +72,11 @@ static void* thread_proc(pj_uint32_t *pcounter) /* Test that pj_thread_register() works. */ 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); if (rc != PJ_SUCCESS) { app_perror("...error in pj_thread_register", rc); @@ -90,9 +100,10 @@ static void* thread_proc(pj_uint32_t *pcounter) for (;!quit_flag;) { (*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; } @@ -114,6 +125,7 @@ static int simple_thread(const char *title, unsigned flags) quit_flag = 0; + TRACE__((THIS_FILE, " Creating thread 0..")); rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc, &counter, PJ_THREAD_DEFAULT_STACK_SIZE, @@ -125,7 +137,9 @@ static int simple_thread(const char *title, unsigned flags) return -1010; } - 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) { @@ -144,7 +158,7 @@ static int simple_thread(const char *title, unsigned flags) PJ_LOG(3,(THIS_FILE, "..waiting for thread to quit..")); - pj_thread_sleep(500); + pj_thread_sleep(1500); quit_flag = 1; pj_thread_join(thread); @@ -175,7 +189,7 @@ static int timeslice_test(void) 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; @@ -183,7 +197,7 @@ static int timeslice_test(void) /* Create all threads in suspended mode. */ for (i=0; i i) { PJ_LOG(3,(THIS_FILE, "....ERROR! Thread %d-th is not suspended!", i)); return -30; @@ -211,6 +227,7 @@ static int timeslice_test(void) /* Now resume all threads. */ for (i=0; i= 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 { PJ_LOG(3,(THIS_FILE, @@ -273,6 +299,7 @@ static int timeslice_test(void) diff)); } + pj_pool_release(pool); return 0; } diff --git a/pjlib/src/pjlib-test/timestamp.c b/pjlib/src/pjlib-test/timestamp.c index 484354069..f7ff7874f 100644 --- a/pjlib/src/pjlib-test/timestamp.c +++ b/pjlib/src/pjlib-test/timestamp.c @@ -188,8 +188,14 @@ int timestamp_test(void) } /* 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. */ pj_get_timestamp(&t2); @@ -198,8 +204,10 @@ int timestamp_test(void) elapsed = pj_elapsed_usec(&t1, &t2); 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, " "t2.u32.hi=%u, t2.u32.lo=%u)", diff --git a/pjlib/src/pjlib-test/util.c b/pjlib/src/pjlib-test/util.c index 19b769cb0..ea1d46527 100644 --- a/pjlib/src/pjlib-test/util.c +++ b/pjlib/src/pjlib-test/util.c @@ -19,14 +19,16 @@ #include "test.h" #include +#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)); } #define SERVER 0 diff --git a/pjmedia/build/os-rtems.mak b/pjmedia/build/os-rtems.mak new file mode 100644 index 000000000..208544094 --- /dev/null +++ b/pjmedia/build/os-rtems.mak @@ -0,0 +1,7 @@ +# +# PJMEDIA OS specific configuration for RTEMS OS target. +# + +export PJMEDIA_OBJS += nullsound.o +export SOUND_OBJS = $(NULLSOUND_OBJS) + diff --git a/pjmedia/src/pjmedia-codec/gsm/config.h b/pjmedia/src/pjmedia-codec/gsm/config.h index 4dd0f2741..2603c42cb 100644 --- a/pjmedia/src/pjmedia-codec/gsm/config.h +++ b/pjmedia/src/pjmedia-codec/gsm/config.h @@ -9,30 +9,31 @@ #ifndef CONFIG_H #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 */ + diff --git a/pjmedia/src/test/main.c b/pjmedia/src/test/main.c index 31acaec77..89d9e6595 100644 --- a/pjmedia/src/test/main.c +++ b/pjmedia/src/test/main.c @@ -18,6 +18,17 @@ */ #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 +# include +# include +# include "../../../pjlib/include/rtems-network-config.h" +#endif + + int main() { int rc;