Merge-in RTEMS port patch by Phil Torre <ptorre@zetron.com>, alpha release.

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@433 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
Benny Prijono 2006-05-10 19:24:40 +00:00
parent 7a6e84fc2c
commit 42c5b9e200
42 changed files with 1560 additions and 211 deletions

47
README-configure Normal file
View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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 := /

9
build/m-mpc860.mak Normal file
View File

@ -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 :=

17
build/os-rtems.mak Normal file
View File

@ -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 :=

View File

@ -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); \

48
configure vendored
View File

@ -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

46
pjlib/build/os-rtems.mak Normal file
View File

@ -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

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -53,6 +53,8 @@
# include <pj/compat/os_sunos.h>
#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."
#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

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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 <pj/os.h>
#include <pj/assert.h>
@ -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 <ptorre@zetron.com>.
*/
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 <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);
#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());

162
pjlib/src/pj/os_rwmutex.c Normal file
View File

@ -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;
}

View File

@ -17,23 +17,30 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pj/os.h>
#include <pj/errno.h>
#include <pj/compat/time.h>
#if defined(PJ_HAS_UNISTD_H) && PJ_HAS_UNISTD_H!=0
# include <unistd.h>
#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;
}

View File

@ -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;

View File

@ -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());

View File

@ -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;

View File

@ -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<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) {
app_perror("...error in pj_ioqueue_unregister", rc);
@ -570,9 +592,11 @@ static int bench_test(int bufsize, int inactive_sock_count)
pj_ioqueue_t *ioque = NULL;
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.
pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);
@ -691,9 +715,15 @@ static int bench_test(int bufsize, int inactive_sock_count)
rc = pj_ioqueue_sendto(ckey, &write_op, send_buf, &bytes, 0,
&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;
}
}
// Begin time.
pj_get_timestamp(&t1);
@ -701,8 +731,11 @@ static int bench_test(int bufsize, int inactive_sock_count)
// Poll the queue until we've got completion event in the server side.
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);
// End time.
@ -749,11 +782,14 @@ static int bench_test(int bufsize, int inactive_sock_count)
}
// 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);
pj_pool_release( pool);
return rc;

View File

@ -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();
}

View File

@ -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<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';
}
@ -56,13 +62,16 @@ static int pool_test_pool()
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;
}
*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<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();
@ -117,11 +129,11 @@ int pool_perf_test()
pool_time2 += (end.u32.lo - start.u32.lo);
}
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;
if (pool_time < pool_time2)
@ -129,7 +141,7 @@ int pool_perf_test()
else
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)));
return 0;

View File

@ -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_ */

View File

@ -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);

View File

@ -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

View File

@ -21,11 +21,11 @@
#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
#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

View File

@ -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<NUM_THREADS; ++i) {
counter[i] = 0;
counter[i] = i;
rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc,
&counter[i],
PJ_THREAD_DEFAULT_STACK_SIZE,
@ -198,11 +212,13 @@ static int timeslice_test(void)
/* Sleep for 1 second.
* 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));
return -30;
@ -211,6 +227,7 @@ static int timeslice_test(void)
/* 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) {
app_perror("...ERROR in pj_thread_resume()", rc);
@ -222,18 +239,23 @@ static int timeslice_test(void)
* The longer we sleep, the more accurate the calculation will be,
* 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. */
quit_flag = 1;
/* 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) {
app_perror("...ERROR in pj_thread_join()", rc);
return -50;
}
TRACE__((THIS_FILE, " Destroying thread %d [%p]..", i, thread[i]));
rc = pj_thread_destroy(thread[i]);
if (rc != PJ_SUCCESS) {
app_perror("...ERROR in pj_thread_destroy()", rc);
@ -241,6 +263,8 @@ static int timeslice_test(void)
}
}
TRACE__((THIS_FILE, " Main thread calculating time slices.."));
/* Now examine the value of the counters.
* Check that all threads had equal proportion of processing.
*/
@ -263,9 +287,11 @@ static int timeslice_test(void)
*/
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 {
PJ_LOG(3,(THIS_FILE,
@ -273,6 +299,7 @@ static int timeslice_test(void)
diff));
}
pj_pool_release(pool);
return 0;
}

View File

@ -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)",

View File

@ -19,14 +19,16 @@
#include "test.h"
#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));
}
#define SERVER 0

View File

@ -0,0 +1,7 @@
#
# PJMEDIA OS specific configuration for RTEMS OS target.
#
export PJMEDIA_OBJS += nullsound.o
export SOUND_OBJS = $(NULLSOUND_OBJS)

View File

@ -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 */

View File

@ -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 <bsp.h>
# include <rtems.h>
# include <rtems/rtems_bsdnet.h>
# include "../../../pjlib/include/rtems-network-config.h"
#endif
int main()
{
int rc;