Re #2062: Remove deprecated Linux kernel implementation
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@5692 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
945170f7b2
commit
5b52b9b2e8
|
@ -1,43 +0,0 @@
|
|||
|
||||
include $(KERNEL_DIR)/.config
|
||||
|
||||
#
|
||||
# Basic kernel compilation flags.
|
||||
#
|
||||
export OS_CFLAGS := $(CC_DEF)PJ_LINUX_KERNEL=1 -D__KERNEL__ \
|
||||
-I$(KERNEL_DIR)/include -iwithprefix include \
|
||||
-nostdinc -msoft-float
|
||||
|
||||
#
|
||||
# Additional kernel compilation flags are taken from the kernel Makefile
|
||||
# itself.
|
||||
#
|
||||
|
||||
KERNEL_CFLAGS := \
|
||||
$(shell cd $(KERNEL_DIR) ; \
|
||||
make script SCRIPT='@echo $$(CFLAGS) $$(CFLAGS_MODULE)' $(KERNEL_ARCH))
|
||||
|
||||
export OS_CFLAGS += $(KERNEL_CFLAGS)
|
||||
|
||||
# -DMODULE -I$(KERNEL_DIR)/include -nostdinc \
|
||||
# -Wstrict-prototypes \
|
||||
# -Wno-trigraphs -fno-strict-aliasing -fno-common \
|
||||
# -msoft-float -m32 -fno-builtin-sprintf -fno-builtin-log2\
|
||||
# -fno-builtin-puts -mpreferred-stack-boundary=2 \
|
||||
# -fno-unit-at-a-time -march=i686 -mregparm=3 \
|
||||
# -iwithprefix include
|
||||
|
||||
#export OS_CFLAGS += -U__i386__ -Ui386 -D__arch_um__ -DSUBARCH=\"i386\" \
|
||||
# -D_LARGEFILE64_SOURCE -I$(KERNEL_DIR)/arch/um/include \
|
||||
# -Derrno=kernel_errno \
|
||||
# -I$(KERNEL_DIR)/arch/um/kernel/tt/include \
|
||||
# -I$(KERNEL_DIR)/arch/um/kernel/skas/include \
|
||||
|
||||
|
||||
export OS_CXXFLAGS :=
|
||||
|
||||
export OS_LDFLAGS :=
|
||||
|
||||
export OS_SOURCES :=
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
#
|
||||
# OS specific configuration for Linux Kernel module target.
|
||||
#
|
||||
|
||||
#
|
||||
# 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 += compat/sigjmp.o compat/setjmp_i386.o \
|
||||
compat/longjmp_i386.o compat/string.o \
|
||||
addr_resolv_linux_kernel.o \
|
||||
guid_simple.o \
|
||||
log_writer_printk.o pool_policy_kmalloc.o \
|
||||
os_error_linux_kernel.o os_core_linux_kernel.o \
|
||||
os_time_linux_kernel.o os_timestamp_common.o \
|
||||
os_timestamp_linux_kernel.o \
|
||||
sock_linux_kernel.o sock_select.o
|
||||
|
||||
# For IOQueue, we can use either epoll or select
|
||||
export PJLIB_OBJS += ioqueue_epoll.o
|
||||
#export PJLIB_OBJS += ioqueue_select.o
|
||||
|
||||
export PJLIB_OBJS += sock_qos_bsd.o
|
||||
|
||||
#
|
||||
# TEST_OBJS are operating system specific object files to be included in
|
||||
# the test application.
|
||||
#
|
||||
export TEST_OBJS += main_mod.o
|
||||
|
||||
#
|
||||
# Additional CFLAGS
|
||||
#
|
||||
export TEST_CFLAGS += -msoft-float
|
||||
|
||||
#
|
||||
# Additional LD_FLAGS for this target.
|
||||
#
|
||||
export TEST_LDFLAGS += -lgcc
|
||||
|
||||
|
||||
#
|
||||
# TARGETS are make targets in the Makefile, to be executed for this given
|
||||
# operating system.
|
||||
#
|
||||
export TARGETS := pjlib.ko pjlib-test.ko
|
||||
|
||||
|
|
@ -28,13 +28,6 @@
|
|||
#if defined(PJ_HAS_ASSERT_H) && PJ_HAS_ASSERT_H != 0
|
||||
# include <assert.h>
|
||||
|
||||
#elif defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL != 0
|
||||
# define assert(expr) do { \
|
||||
if (!(expr)) \
|
||||
printk("!!ASSERTION FAILED: [%s:%d] \"" #expr "\"\n",\
|
||||
__FILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
# warning "assert() is not implemented"
|
||||
# define assert(expr)
|
||||
|
|
|
@ -31,21 +31,6 @@
|
|||
# define PJ_HIGHPREC_VALUE_IS_ZERO(a) (a==0)
|
||||
# define pj_highprec_mod(a,b) (a=fmod(a,b))
|
||||
|
||||
#elif defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL != 0
|
||||
|
||||
# include <asm/div64.h>
|
||||
|
||||
typedef pj_int64_t pj_highprec_t;
|
||||
|
||||
# define pj_highprec_div(a1,a2) do_div(a1,a2)
|
||||
# define pj_highprec_mod(a1,a2) (a1=do_mod(a1, a2))
|
||||
|
||||
PJ_INLINE(pj_int64_t) do_mod( pj_int64_t a1, pj_int64_t a2)
|
||||
{
|
||||
return do_div(a1,a2);
|
||||
}
|
||||
|
||||
|
||||
#elif defined(PJ_HAS_INT64) && PJ_HAS_INT64 != 0
|
||||
/*
|
||||
* Next choice is to use 64-bit arithmatics.
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
* Copyright (C) 2003-2008 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
|
||||
*/
|
||||
#ifndef __PJ_COMPAT_OS_LINUX_KERNEL_H__
|
||||
#define __PJ_COMPAT_OS_LINUX_KERNEL_H__
|
||||
|
||||
/**
|
||||
* @file os_linux.h
|
||||
* @brief Describes Linux operating system specifics.
|
||||
*/
|
||||
|
||||
#define PJ_OS_NAME "linux-module"
|
||||
|
||||
#define PJ_HAS_ARPA_INET_H 0
|
||||
#define PJ_HAS_ASSERT_H 0
|
||||
#define PJ_HAS_CTYPE_H 0
|
||||
#define PJ_HAS_ERRNO_H 0
|
||||
#define PJ_HAS_LINUX_SOCKET_H 1
|
||||
#define PJ_HAS_MALLOC_H 0
|
||||
#define PJ_HAS_NETDB_H 0
|
||||
#define PJ_HAS_NETINET_IN_H 0
|
||||
#define PJ_HAS_SETJMP_H 0
|
||||
#define PJ_HAS_STDARG_H 1
|
||||
#define PJ_HAS_STDDEF_H 0
|
||||
#define PJ_HAS_STDIO_H 0
|
||||
#define PJ_HAS_STDLIB_H 0
|
||||
#define PJ_HAS_STRING_H 0
|
||||
#define PJ_HAS_SYS_IOCTL_H 0
|
||||
#define PJ_HAS_SYS_SELECT_H 0
|
||||
#define PJ_HAS_SYS_SOCKET_H 0
|
||||
#define PJ_HAS_SYS_TIME_H 0
|
||||
#define PJ_HAS_SYS_TIMEB_H 0
|
||||
#define PJ_HAS_SYS_TYPES_H 0
|
||||
#define PJ_HAS_TIME_H 0
|
||||
#define PJ_HAS_UNISTD_H 0
|
||||
|
||||
#define PJ_HAS_MSWSOCK_H 0
|
||||
#define PJ_HAS_WINSOCK_H 0
|
||||
#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
|
||||
* 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 0
|
||||
|
||||
/* Is errno a good way to retrieve OS errors?
|
||||
* (probably no for linux kernel)
|
||||
* If you answer no here, you'll need to tell pjlib how to get OS
|
||||
* error (a compile error will tell you exactly where)
|
||||
*/
|
||||
#define PJ_HAS_ERRNO_VAR 0
|
||||
|
||||
/* 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 EAGAIN
|
||||
|
||||
/* 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
|
||||
|
||||
#ifndef PJ_HAS_THREADS
|
||||
# define PJ_HAS_THREADS (1)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Declare __FD_SETSIZE now before including <linux*>.
|
||||
*/
|
||||
#define __FD_SETSIZE PJ_IOQUEUE_MAX_HANDLES
|
||||
|
||||
#define NULL ((void*)0)
|
||||
|
||||
#include <linux/module.h> /* Needed by all modules */
|
||||
#include <linux/kernel.h> /* Needed for KERN_INFO */
|
||||
|
||||
#define __PJ_EXPORT_SYMBOL(a) EXPORT_SYMBOL(a);
|
||||
|
||||
/*
|
||||
* Override features.
|
||||
*/
|
||||
#define PJ_HAS_FLOATING_POINT 0
|
||||
#define PJ_HAS_MALLOC 0
|
||||
#define PJ_HAS_SEMAPHORE 0
|
||||
#define PJ_HAS_EVENT_OBJ 0
|
||||
#define PJ_HAS_HIGH_RES_TIMER 1
|
||||
#ifndef PJ_OS_HAS_CHECK_STACK
|
||||
# define PJ_OS_HAS_CHECK_STACK 0
|
||||
#endif
|
||||
#define PJ_TERM_HAS_COLOR 0
|
||||
#define PJ_NATIVE_STRING_IS_UNICODE 0
|
||||
|
||||
#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__ */
|
||||
|
|
@ -44,20 +44,6 @@
|
|||
# define platform_rand rand
|
||||
# endif
|
||||
|
||||
#elif defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL != 0
|
||||
/*
|
||||
* Linux kernel mode random number generator.
|
||||
*/
|
||||
# include <linux/random.h>
|
||||
# define platform_srand(seed)
|
||||
|
||||
PJ_INLINE(int) platform_rand(void)
|
||||
{
|
||||
int value;
|
||||
get_random_bytes((void*)&value, sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
#else
|
||||
# warning "platform_rand() is not implemented"
|
||||
# define platform_rand() 1
|
||||
|
|
|
@ -35,54 +35,6 @@
|
|||
# define pj_longjmp(buf,d) longjmp(buf,d)
|
||||
# endif
|
||||
|
||||
#elif defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL != 0 && \
|
||||
defined(PJ_M_I386) && PJ_M_I386 != 0
|
||||
|
||||
/*
|
||||
* These are taken from uClibc.
|
||||
* Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
|
||||
*/
|
||||
# if defined __USE_MISC || defined _ASM
|
||||
# define JB_BX 0
|
||||
# define JB_SI 1
|
||||
# define JB_DI 2
|
||||
# define JB_BP 3
|
||||
# define JB_SP 4
|
||||
# define JB_PC 5
|
||||
# define JB_SIZE 24
|
||||
# endif
|
||||
|
||||
# ifndef _ASM
|
||||
typedef int __jmp_buf[6];
|
||||
|
||||
/* A `sigset_t' has a bit for each signal. */
|
||||
# define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int)))
|
||||
typedef struct __sigset_t_tag
|
||||
{
|
||||
unsigned long int __val[_SIGSET_NWORDS];
|
||||
} __sigset_t;
|
||||
|
||||
/* Calling environment, plus possibly a saved signal mask. */
|
||||
typedef struct __jmp_buf_tag /* C++ doesn't like tagless structs. */
|
||||
{
|
||||
/* NOTE: The machine-dependent definitions of `__sigsetjmp'
|
||||
assume that a `jmp_buf' begins with a `__jmp_buf' and that
|
||||
`__mask_was_saved' follows it. Do not move these members
|
||||
or add others before it. */
|
||||
__jmp_buf __jmpbuf; /* Calling environment. */
|
||||
int __mask_was_saved; /* Saved the signal mask? */
|
||||
// we never saved the mask.
|
||||
__sigset_t __saved_mask; /* Saved signal mask. */
|
||||
} jmp_buf[1];
|
||||
|
||||
typedef jmp_buf sigjmp_buf;
|
||||
typedef jmp_buf pj_jmp_buf;
|
||||
|
||||
PJ_DECL(int) pj_setjmp(pj_jmp_buf env);
|
||||
PJ_DECL(void) pj_longjmp(pj_jmp_buf env, int val) __attribute__((noreturn));
|
||||
|
||||
# endif /* _ASM */
|
||||
|
||||
#elif defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
|
||||
/* Symbian framework don't use setjmp/longjmp */
|
||||
|
||||
|
|
|
@ -184,34 +184,6 @@
|
|||
#undef s6_addr
|
||||
#undef sin_zero
|
||||
|
||||
/*
|
||||
* Linux kernel specifics
|
||||
*/
|
||||
#if defined(PJ_LINUX_KERNEL)
|
||||
# include <linux/net.h>
|
||||
# include <asm/ioctls.h> /* FIONBIO */
|
||||
# include <linux/syscalls.h> /* sys_select() */
|
||||
# include <asm/uaccess.h> /* set/get_fs() */
|
||||
|
||||
typedef int socklen_t;
|
||||
# define getsockopt sys_getsockopt
|
||||
|
||||
/*
|
||||
* Wrapper for select() in Linux kernel.
|
||||
*/
|
||||
PJ_INLINE(int) select(int n, fd_set *inp, fd_set *outp, fd_set *exp,
|
||||
struct timeval *tvp)
|
||||
{
|
||||
int count;
|
||||
mm_segment_t oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
count = sys_select(n, inp, outp, exp, tvp);
|
||||
set_fs(oldfs);
|
||||
return count;
|
||||
}
|
||||
#endif /* PJ_LINUX_KERNEL */
|
||||
|
||||
|
||||
/*
|
||||
* This will finally be obsoleted, since it should be declared in
|
||||
* os_auto.h
|
||||
|
|
|
@ -115,12 +115,6 @@
|
|||
# define PJ_WIN32 1
|
||||
# include <pj/compat/os_win32.h>
|
||||
|
||||
#elif defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL!=0
|
||||
/*
|
||||
* Linux kernel
|
||||
*/
|
||||
# include <pj/compat/os_linux_kernel.h>
|
||||
|
||||
#elif defined(PJ_LINUX) || defined(linux) || defined(__linux)
|
||||
/*
|
||||
* Linux
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <pj/addr_resolv.h>
|
||||
|
||||
PJ_DEF(pj_status_t) pj_gethostbyname(const pj_str_t *hostname, pj_hostent *phe)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/* longjmp for i386.
|
||||
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define _ASM
|
||||
#define _SETJMP_H
|
||||
#define PJ_LINUX_KERNEL 1
|
||||
#include <pj/compat/setjmp.h>
|
||||
|
||||
.global __longjmp
|
||||
.type __longjmp,%function
|
||||
.align 4
|
||||
__longjmp:
|
||||
movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */
|
||||
movl 8(%esp), %eax /* Second argument is return value. */
|
||||
/* Save the return address now. */
|
||||
movl (JB_PC*4)(%ecx), %edx
|
||||
/* Restore registers. */
|
||||
movl (JB_BX*4)(%ecx), %ebx
|
||||
movl (JB_SI*4)(%ecx), %esi
|
||||
movl (JB_DI*4)(%ecx), %edi
|
||||
movl (JB_BP*4)(%ecx), %ebp
|
||||
movl (JB_SP*4)(%ecx), %esp
|
||||
/* Jump to saved PC. */
|
||||
jmp *%edx
|
||||
.size __longjmp,.-__longjmp
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/* setjmp for i386, ELF version.
|
||||
Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define _ASM
|
||||
#define _SETJMP_H
|
||||
#define PJ_LINUX_KERNEL 1
|
||||
#include <pj/compat/setjmp.h>
|
||||
|
||||
|
||||
.global __sigsetjmp
|
||||
.type __sigsetjmp,%function
|
||||
.align 4
|
||||
|
||||
__sigsetjmp:
|
||||
movl 4 (%esp), %eax
|
||||
/* Save registers. */
|
||||
movl %ebx, (0 *4)(%eax)
|
||||
movl %esi, (1 *4)(%eax)
|
||||
movl %edi, (2 *4)(%eax)
|
||||
/* Save SP as it will be after we return. */
|
||||
leal 4(%esp), %ecx
|
||||
movl %ecx, (4 *4)(%eax)
|
||||
/* Save PC we are returning to now. */
|
||||
movl 0(%esp), %ecx
|
||||
movl %ecx, (5 *4)(%eax)
|
||||
/* Save caller's frame pointer. */
|
||||
movl %ebp, (3 *4)(%eax)
|
||||
|
||||
/* Make a tail call to __sigjmp_save; it takes the same args. */
|
||||
#ifdef __PIC__
|
||||
/* We cannot use the PLT, because it requires that %ebx be set, but
|
||||
we can't save and restore our caller's value. Instead, we do an
|
||||
indirect jump through the GOT, using for the temporary register
|
||||
%ecx, which is call-clobbered. */
|
||||
call .Lhere
|
||||
.Lhere:
|
||||
popl %ecx
|
||||
addl $_GLOBAL_OFFSET_TABLE_+[.- .Lhere ], %ecx
|
||||
movl __sigjmp_save @GOT (%ecx), %ecx
|
||||
jmp *%ecx
|
||||
#else
|
||||
jmp __sigjmp_save
|
||||
#endif
|
||||
.size __sigsetjmp,.-__sigsetjmp
|
||||
|
|
@ -546,9 +546,6 @@ pj_bool_t ioqueue_dispatch_read_event( pj_ioqueue_t *ioqueue,
|
|||
# elif (defined(PJ_HAS_UNISTD_H) && PJ_HAS_UNISTD_H != 0)
|
||||
bytes_read = read(h->fd, read_op->buf, bytes_read);
|
||||
rc = (bytes_read >= 0) ? PJ_SUCCESS : pj_get_os_error();
|
||||
# elif defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL != 0
|
||||
bytes_read = sys_read(h->fd, read_op->buf, bytes_read);
|
||||
rc = (bytes_read >= 0) ? PJ_SUCCESS : -bytes_read;
|
||||
# else
|
||||
# error "Implement read() for this platform!"
|
||||
# endif
|
||||
|
|
|
@ -37,109 +37,21 @@
|
|||
#include <pj/compat/socket.h>
|
||||
#include <pj/rand.h>
|
||||
|
||||
#if !defined(PJ_LINUX_KERNEL) || PJ_LINUX_KERNEL==0
|
||||
/*
|
||||
* Linux user mode
|
||||
*/
|
||||
# include <sys/epoll.h>
|
||||
# include <errno.h>
|
||||
# include <unistd.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
# define epoll_data data.ptr
|
||||
# define epoll_data_type void*
|
||||
# define ioctl_val_type unsigned long
|
||||
# define getsockopt_val_ptr int*
|
||||
# define os_getsockopt getsockopt
|
||||
# define os_ioctl ioctl
|
||||
# define os_read read
|
||||
# define os_close close
|
||||
# define os_epoll_create epoll_create
|
||||
# define os_epoll_ctl epoll_ctl
|
||||
# define os_epoll_wait epoll_wait
|
||||
#else
|
||||
/*
|
||||
* Linux kernel mode.
|
||||
*/
|
||||
# include <linux/config.h>
|
||||
# include <linux/version.h>
|
||||
# if defined(MODVERSIONS)
|
||||
# include <linux/modversions.h>
|
||||
# endif
|
||||
# include <linux/kernel.h>
|
||||
# include <linux/poll.h>
|
||||
# include <linux/eventpoll.h>
|
||||
# include <linux/syscalls.h>
|
||||
# include <linux/errno.h>
|
||||
# include <linux/unistd.h>
|
||||
# include <asm/ioctls.h>
|
||||
enum EPOLL_EVENTS
|
||||
{
|
||||
EPOLLIN = 0x001,
|
||||
EPOLLOUT = 0x004,
|
||||
EPOLLERR = 0x008,
|
||||
};
|
||||
# define os_epoll_create sys_epoll_create
|
||||
static int os_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
|
||||
{
|
||||
long rc;
|
||||
mm_segment_t oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
rc = sys_epoll_ctl(epfd, op, fd, event);
|
||||
set_fs(oldfs);
|
||||
if (rc) {
|
||||
errno = -rc;
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static int os_epoll_wait(int epfd, struct epoll_event *events,
|
||||
int maxevents, int timeout)
|
||||
{
|
||||
int count;
|
||||
mm_segment_t oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
count = sys_epoll_wait(epfd, events, maxevents, timeout);
|
||||
set_fs(oldfs);
|
||||
return count;
|
||||
}
|
||||
# define os_close sys_close
|
||||
# define os_getsockopt pj_sock_getsockopt
|
||||
static int os_read(int fd, void *buf, size_t len)
|
||||
{
|
||||
long rc;
|
||||
mm_segment_t oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
rc = sys_read(fd, buf, len);
|
||||
set_fs(oldfs);
|
||||
if (rc) {
|
||||
errno = -rc;
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
# define socklen_t unsigned
|
||||
# define ioctl_val_type unsigned long
|
||||
int ioctl(int fd, int opt, ioctl_val_type value);
|
||||
static int os_ioctl(int fd, int opt, ioctl_val_type value)
|
||||
{
|
||||
int rc;
|
||||
mm_segment_t oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
rc = ioctl(fd, opt, value);
|
||||
set_fs(oldfs);
|
||||
if (rc < 0) {
|
||||
errno = -rc;
|
||||
return rc;
|
||||
} else
|
||||
return rc;
|
||||
}
|
||||
# define getsockopt_val_ptr char*
|
||||
|
||||
# define epoll_data data
|
||||
# define epoll_data_type __u32
|
||||
#endif
|
||||
#define epoll_data data.ptr
|
||||
#define epoll_data_type void*
|
||||
#define ioctl_val_type unsigned long
|
||||
#define getsockopt_val_ptr int*
|
||||
#define os_getsockopt getsockopt
|
||||
#define os_ioctl ioctl
|
||||
#define os_read read
|
||||
#define os_close close
|
||||
#define os_epoll_create epoll_create
|
||||
#define os_epoll_ctl epoll_ctl
|
||||
#define os_epoll_wait epoll_wait
|
||||
|
||||
#define THIS_FILE "ioq_epoll"
|
||||
|
||||
|
@ -201,11 +113,7 @@ static void scan_closing_keys(pj_ioqueue_t *ioqueue);
|
|||
*/
|
||||
PJ_DEF(const char*) pj_ioqueue_name(void)
|
||||
{
|
||||
#if defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL!=0
|
||||
return "epoll-kernel";
|
||||
#else
|
||||
return "epoll";
|
||||
#endif
|
||||
return "epoll";
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <pj/ioqueue.h>
|
||||
#include <pj/os.h>
|
||||
#include <pj/log.h>
|
||||
#include <pj/list.h>
|
||||
#include <pj/pool.h>
|
||||
#include <pj/string.h>
|
||||
#include <pj/assert.h>
|
||||
#include <pj/sock.h>
|
||||
|
||||
#define THIS_FILE "ioqueue"
|
||||
|
||||
#define PJ_IOQUEUE_IS_READ_OP(op) \
|
||||
((op & PJ_IOQUEUE_OP_READ) || (op & PJ_IOQUEUE_OP_RECV_FROM))
|
||||
#define PJ_IOQUEUE_IS_WRITE_OP(op) \
|
||||
((op & PJ_IOQUEUE_OP_WRITE) || (op & PJ_IOQUEUE_OP_SEND_TO))
|
||||
|
||||
|
||||
#if PJ_HAS_TCP
|
||||
# define PJ_IOQUEUE_IS_ACCEPT_OP(op) (op & PJ_IOQUEUE_OP_ACCEPT)
|
||||
# define PJ_IOQUEUE_IS_CONNECT_OP(op) (op & PJ_IOQUEUE_OP_CONNECT)
|
||||
#else
|
||||
# define PJ_IOQUEUE_IS_ACCEPT_OP(op) 0
|
||||
# define PJ_IOQUEUE_IS_CONNECT_OP(op) 0
|
||||
#endif
|
||||
|
||||
#if defined(PJ_DEBUG) && PJ_DEBUG != 0
|
||||
# define VALIDATE_FD_SET 1
|
||||
#else
|
||||
# define VALIDATE_FD_SET 0
|
||||
#endif
|
||||
|
||||
struct pj_ioqueue_key_t
|
||||
{
|
||||
PJ_DECL_LIST_MEMBER(struct pj_ioqueue_key_t)
|
||||
pj_sock_t fd;
|
||||
pj_ioqueue_operation_e op;
|
||||
void *user_data;
|
||||
pj_ioqueue_callback cb;
|
||||
};
|
||||
|
||||
struct pj_ioqueue_t
|
||||
{
|
||||
};
|
||||
|
||||
PJ_DEF(pj_ioqueue_t*) pj_ioqueue_create(pj_pool_t *pool, pj_size_t max_fd)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_ioqueue_destroy(pj_ioqueue_t *ioque)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_ioqueue_key_t*) pj_ioqueue_register( pj_pool_t *pool,
|
||||
pj_ioqueue_t *ioque,
|
||||
pj_oshandle_t sock,
|
||||
void *user_data,
|
||||
const pj_ioqueue_callback *cb)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_t *ioque,
|
||||
pj_ioqueue_key_t *key)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
PJ_DEF(void*) pj_ioqueue_get_user_data( pj_ioqueue_key_t *key )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioque, const pj_time_val *timeout)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
PJ_DEF(int) pj_ioqueue_read( pj_ioqueue_t *ioque,
|
||||
pj_ioqueue_key_t *key,
|
||||
void *buffer,
|
||||
pj_size_t buflen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
PJ_DEF(int) pj_ioqueue_recvfrom( pj_ioqueue_t *ioque,
|
||||
pj_ioqueue_key_t *key,
|
||||
void *buffer,
|
||||
pj_size_t buflen,
|
||||
pj_sockaddr_t *addr,
|
||||
int *addrlen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
PJ_DEF(int) pj_ioqueue_write( pj_ioqueue_t *ioque,
|
||||
pj_ioqueue_key_t *key,
|
||||
const void *data,
|
||||
pj_size_t datalen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
PJ_DEF(int) pj_ioqueue_sendto( pj_ioqueue_t *ioque,
|
||||
pj_ioqueue_key_t *key,
|
||||
const void *data,
|
||||
pj_size_t datalen,
|
||||
const pj_sockaddr_t *addr,
|
||||
int addrlen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if PJ_HAS_TCP
|
||||
/*
|
||||
* Initiate overlapped accept() operation.
|
||||
*/
|
||||
PJ_DEF(int) pj_ioqueue_accept( pj_ioqueue_t *ioqueue,
|
||||
pj_ioqueue_key_t *key,
|
||||
pj_sock_t *new_sock,
|
||||
pj_sockaddr_t *local,
|
||||
pj_sockaddr_t *remote,
|
||||
int *addrlen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiate overlapped connect() operation (well, it's non-blocking actually,
|
||||
* since there's no overlapped version of connect()).
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_ioqueue_connect( pj_ioqueue_t *ioqueue,
|
||||
pj_ioqueue_key_t *key,
|
||||
const pj_sockaddr_t *addr,
|
||||
int addrlen )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif /* PJ_HAS_TCP */
|
||||
|
|
@ -1,698 +0,0 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <pj/os.h>
|
||||
#include <pj/assert.h>
|
||||
#include <pj/pool.h>
|
||||
#include <pj/log.h>
|
||||
#include <pj/except.h>
|
||||
#include <pj/errno.h>
|
||||
#include <pj/string.h>
|
||||
#include <pj/compat/high_precision.h>
|
||||
#include <pj/compat/sprintf.h>
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/version.h>
|
||||
#if defined(MODVERSIONS)
|
||||
#include <linux/modversions.h>
|
||||
#endif
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
//#include <linux/tqueue.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/signal.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/semaphore.h>
|
||||
|
||||
#define THIS_FILE "oslinuxkern"
|
||||
|
||||
struct pj_thread_t
|
||||
{
|
||||
/** Thread's name. */
|
||||
char obj_name[PJ_MAX_OBJ_NAME];
|
||||
|
||||
/** Linux task structure for thread. */
|
||||
struct task_struct *thread;
|
||||
|
||||
/** Flags (specified in pj_thread_create) */
|
||||
unsigned flags;
|
||||
|
||||
/** Task queue needed to launch thread. */
|
||||
//struct tq_struct tq;
|
||||
|
||||
/** Semaphore needed to control thread startup. */
|
||||
struct semaphore startstop_sem;
|
||||
|
||||
/** Semaphore to suspend thread during startup. */
|
||||
struct semaphore suspend_sem;
|
||||
|
||||
/** Queue thread is waiting on. Gets initialized by
|
||||
thread_initialize, can be used by thread itself.
|
||||
*/
|
||||
wait_queue_head_t queue;
|
||||
|
||||
/** Flag to tell thread whether to die or not.
|
||||
When the thread receives a signal, it must check
|
||||
the value of terminate and call thread_deinitialize and terminate
|
||||
if set.
|
||||
*/
|
||||
int terminate;
|
||||
|
||||
/** Thread's entry. */
|
||||
pj_thread_proc *func;
|
||||
|
||||
/** Argument. */
|
||||
void *arg;
|
||||
};
|
||||
|
||||
struct pj_atomic_t
|
||||
{
|
||||
atomic_t atom;
|
||||
};
|
||||
|
||||
struct pj_mutex_t
|
||||
{
|
||||
struct semaphore sem;
|
||||
pj_bool_t recursive;
|
||||
pj_thread_t *owner;
|
||||
int own_count;
|
||||
};
|
||||
|
||||
struct pj_sem_t
|
||||
{
|
||||
struct semaphore sem;
|
||||
};
|
||||
|
||||
/*
|
||||
* Static global variables.
|
||||
*/
|
||||
#define MAX_TLS_ID 32
|
||||
static void *tls_values[MAX_TLS_ID];
|
||||
static int tls_id;
|
||||
static long thread_tls_id;
|
||||
static spinlock_t critical_section = SPIN_LOCK_UNLOCKED;
|
||||
static unsigned long spinlock_flags;
|
||||
static pj_thread_t main_thread;
|
||||
|
||||
/* private functions */
|
||||
//#define TRACE_(expr) PJ_LOG(3,expr)
|
||||
#define TRACE_(x)
|
||||
|
||||
|
||||
/* This must be called in the context of the new thread. */
|
||||
static void thread_initialize( pj_thread_t *thread )
|
||||
{
|
||||
TRACE_((THIS_FILE, "---new thread initializing..."));
|
||||
|
||||
/* Set TLS */
|
||||
pj_thread_local_set(thread_tls_id, thread);
|
||||
|
||||
/* fill in thread structure */
|
||||
thread->thread = current;
|
||||
pj_assert(thread->thread != NULL);
|
||||
|
||||
/* set signal mask to what we want to respond */
|
||||
siginitsetinv(¤t->blocked,
|
||||
sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM));
|
||||
|
||||
/* initialise wait queue */
|
||||
init_waitqueue_head(&thread->queue);
|
||||
|
||||
/* initialise termination flag */
|
||||
thread->terminate = 0;
|
||||
|
||||
/* set name of this process (making sure obj_name is null
|
||||
* terminated first)
|
||||
*/
|
||||
thread->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
|
||||
sprintf(current->comm, thread->obj_name);
|
||||
|
||||
/* tell the creator that we are ready and let him continue */
|
||||
up(&thread->startstop_sem);
|
||||
}
|
||||
|
||||
/* cleanup of thread. Called by the exiting thread. */
|
||||
static void thread_deinitialize(pj_thread_t *thread)
|
||||
{
|
||||
/* we are terminating */
|
||||
|
||||
/* lock the kernel, the exit will unlock it */
|
||||
thread->thread = NULL;
|
||||
mb();
|
||||
|
||||
/* notify the stop_kthread() routine that we are terminating. */
|
||||
up(&thread->startstop_sem);
|
||||
|
||||
/* the kernel_thread that called clone() does a do_exit here. */
|
||||
|
||||
/* there is no race here between execution of the "killer" and
|
||||
real termination of the thread (race window between up and do_exit),
|
||||
since both the thread and the "killer" function are running with
|
||||
the kernel lock held.
|
||||
The kernel lock will be freed after the thread exited, so the code
|
||||
is really not executed anymore as soon as the unload functions gets
|
||||
the kernel lock back.
|
||||
The init process may not have made the cleanup of the process here,
|
||||
but the cleanup can be done safely with the module unloaded.
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
static int thread_proc(void *arg)
|
||||
{
|
||||
pj_thread_t *thread = arg;
|
||||
|
||||
TRACE_((THIS_FILE, "---new thread starting!"));
|
||||
|
||||
/* Initialize thread. */
|
||||
thread_initialize( thread );
|
||||
|
||||
/* Wait if created suspended. */
|
||||
if (thread->flags & PJ_THREAD_SUSPENDED) {
|
||||
TRACE_((THIS_FILE, "---new thread suspended..."));
|
||||
down(&thread->suspend_sem);
|
||||
}
|
||||
|
||||
TRACE_((THIS_FILE, "---new thread running..."));
|
||||
|
||||
pj_assert(thread->func != NULL);
|
||||
|
||||
/* Call thread's entry. */
|
||||
(*thread->func)(thread->arg);
|
||||
|
||||
TRACE_((THIS_FILE, "---thread exiting..."));
|
||||
|
||||
/* Cleanup thread. */
|
||||
thread_deinitialize(thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The very task entry. */
|
||||
static void kthread_launcher(void *arg)
|
||||
{
|
||||
TRACE_((THIS_FILE, "...launching thread!..."));
|
||||
kernel_thread(&thread_proc, arg, 0);
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_init(void)
|
||||
{
|
||||
pj_status_t rc;
|
||||
|
||||
PJ_LOG(5, ("pj_init", "Initializing PJ Library.."));
|
||||
|
||||
rc = pj_thread_init();
|
||||
if (rc != PJ_SUCCESS)
|
||||
return rc;
|
||||
|
||||
/* Initialize exception ID for the pool.
|
||||
* Must do so after critical section is configured.
|
||||
*/
|
||||
rc = pj_exception_id_alloc("PJLIB/No memory", &PJ_NO_MEMORY_EXCEPTION);
|
||||
if (rc != PJ_SUCCESS)
|
||||
return rc;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_uint32_t) pj_getpid(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_thread_register ( const char *cstr_thread_name,
|
||||
pj_thread_desc desc,
|
||||
pj_thread_t **ptr_thread)
|
||||
{
|
||||
char stack_ptr;
|
||||
pj_thread_t *thread = (pj_thread_t *)desc;
|
||||
pj_str_t thread_name = pj_str((char*)cstr_thread_name);
|
||||
|
||||
/* Size sanity check. */
|
||||
if (sizeof(pj_thread_desc) < sizeof(pj_thread_t)) {
|
||||
pj_assert(!"Not enough pj_thread_desc size!");
|
||||
return PJ_EBUG;
|
||||
}
|
||||
|
||||
/* If a thread descriptor has been registered before, just return it. */
|
||||
if (pj_thread_local_get (thread_tls_id) != 0) {
|
||||
// 2006-02-26 bennylp:
|
||||
// This wouldn't work in all cases!.
|
||||
// If thread is created by external module (e.g. sound thread),
|
||||
// thread may be reused while the pool used for the thread descriptor
|
||||
// has been deleted by application.
|
||||
//*thread_ptr = (pj_thread_t*)pj_thread_local_get (thread_tls_id);
|
||||
//return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/* Initialize and set the thread entry. */
|
||||
pj_bzero(desc, sizeof(struct pj_thread_t));
|
||||
|
||||
if(cstr_thread_name && pj_strlen(&thread_name) < sizeof(thread->obj_name)-1)
|
||||
pj_sprintf(thread->obj_name, cstr_thread_name, thread->thread);
|
||||
else
|
||||
pj_snprintf(thread->obj_name, sizeof(thread->obj_name),
|
||||
"thr%p", (void*)thread->thread);
|
||||
|
||||
/* Initialize. */
|
||||
thread_initialize(thread);
|
||||
|
||||
/* Eat semaphore. */
|
||||
down(&thread->startstop_sem);
|
||||
|
||||
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
|
||||
thread->stk_start = &stack_ptr;
|
||||
thread->stk_size = 0xFFFFFFFFUL;
|
||||
thread->stk_max_usage = 0;
|
||||
#else
|
||||
stack_ptr = '\0';
|
||||
#endif
|
||||
|
||||
*ptr_thread = thread;
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
pj_status_t pj_thread_init(void)
|
||||
{
|
||||
pj_status_t rc;
|
||||
pj_thread_t *dummy;
|
||||
|
||||
rc = pj_thread_local_alloc(&thread_tls_id);
|
||||
if (rc != PJ_SUCCESS)
|
||||
return rc;
|
||||
|
||||
return pj_thread_register("pjlib-main", (long*)&main_thread, &dummy);
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool, const char *thread_name,
|
||||
pj_thread_proc *proc, void *arg,
|
||||
pj_size_t stack_size, unsigned flags,
|
||||
pj_thread_t **ptr_thread)
|
||||
{
|
||||
pj_thread_t *thread;
|
||||
|
||||
TRACE_((THIS_FILE, "pj_thread_create()"));
|
||||
|
||||
PJ_ASSERT_RETURN(pool && proc && ptr_thread, PJ_EINVAL);
|
||||
|
||||
thread = pj_pool_zalloc(pool, sizeof(pj_thread_t));
|
||||
if (!thread)
|
||||
return PJ_ENOMEM;
|
||||
|
||||
PJ_UNUSED_ARG(stack_size);
|
||||
|
||||
/* Thread name. */
|
||||
if (!thread_name)
|
||||
thread_name = "thr%p";
|
||||
|
||||
if (strchr(thread_name, '%')) {
|
||||
pj_snprintf(thread->obj_name, PJ_MAX_OBJ_NAME, thread_name, thread);
|
||||
} else {
|
||||
strncpy(thread->obj_name, thread_name, PJ_MAX_OBJ_NAME);
|
||||
thread->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
|
||||
}
|
||||
|
||||
/* Init thread's semaphore. */
|
||||
TRACE_((THIS_FILE, "...init semaphores..."));
|
||||
init_MUTEX_LOCKED(&thread->startstop_sem);
|
||||
init_MUTEX_LOCKED(&thread->suspend_sem);
|
||||
|
||||
thread->flags = flags;
|
||||
|
||||
if ((flags & PJ_THREAD_SUSPENDED) == 0) {
|
||||
up(&thread->suspend_sem);
|
||||
}
|
||||
|
||||
/* Store the functions and argument. */
|
||||
thread->func = proc;
|
||||
thread->arg = arg;
|
||||
|
||||
/* Save return value. */
|
||||
*ptr_thread = thread;
|
||||
|
||||
/* Create the new thread by running a task through keventd. */
|
||||
|
||||
#if 0
|
||||
/* Initialize the task queue struct. */
|
||||
thread->tq.sync = 0;
|
||||
INIT_LIST_HEAD(&thread->tq.list);
|
||||
thread->tq.routine = kthread_launcher;
|
||||
thread->tq.data = thread;
|
||||
|
||||
/* and schedule it for execution. */
|
||||
schedule_task(&thread->tq);
|
||||
#endif
|
||||
kthread_launcher(thread);
|
||||
|
||||
/* Wait until thread has reached the setup_thread routine. */
|
||||
TRACE_((THIS_FILE, "...wait for the new thread..."));
|
||||
down(&thread->startstop_sem);
|
||||
|
||||
TRACE_((THIS_FILE, "...main thread resumed..."));
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(const char*) pj_thread_get_name(pj_thread_t *thread)
|
||||
{
|
||||
return thread->obj_name;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_thread_resume(pj_thread_t *thread)
|
||||
{
|
||||
up(&thread->suspend_sem);
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_thread_t*) pj_thread_this(void)
|
||||
{
|
||||
return (pj_thread_t*)pj_thread_local_get(thread_tls_id);
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_thread_join(pj_thread_t *p)
|
||||
{
|
||||
TRACE_((THIS_FILE, "pj_thread_join()"));
|
||||
down(&p->startstop_sem);
|
||||
TRACE_((THIS_FILE, " joined!"));
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_thread_destroy(pj_thread_t *thread)
|
||||
{
|
||||
PJ_ASSERT_RETURN(thread != NULL, PJ_EINVALIDOP);
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_thread_sleep(unsigned msec)
|
||||
{
|
||||
pj_highprec_t ticks;
|
||||
pj_thread_t *thread = pj_thread_this();
|
||||
|
||||
PJ_ASSERT_RETURN(thread != NULL, PJ_EBUG);
|
||||
|
||||
/* Use high precision calculation to make sure we don't
|
||||
* crop values:
|
||||
*
|
||||
* ticks = HZ * msec / 1000
|
||||
*/
|
||||
ticks = HZ;
|
||||
pj_highprec_mul(ticks, msec);
|
||||
pj_highprec_div(ticks, 1000);
|
||||
|
||||
TRACE_((THIS_FILE, "this thread will sleep for %u ticks", ticks));
|
||||
interruptible_sleep_on_timeout( &thread->queue, ticks);
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
PJ_DEF(pj_status_t) pj_atomic_create( pj_pool_t *pool,
|
||||
pj_atomic_value_t value,
|
||||
pj_atomic_t **ptr_var)
|
||||
{
|
||||
pj_atomic_t *t = pj_pool_calloc(pool, 1, sizeof(pj_atomic_t));
|
||||
if (!t) return PJ_ENOMEM;
|
||||
|
||||
atomic_set(&t->atom, value);
|
||||
*ptr_var = t;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_atomic_destroy( pj_atomic_t *var )
|
||||
{
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(void) pj_atomic_set(pj_atomic_t *var, pj_atomic_value_t value)
|
||||
{
|
||||
atomic_set(&var->atom, value);
|
||||
}
|
||||
|
||||
PJ_DEF(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *var)
|
||||
{
|
||||
return atomic_read(&var->atom);
|
||||
}
|
||||
|
||||
PJ_DEF(void) pj_atomic_inc(pj_atomic_t *var)
|
||||
{
|
||||
atomic_inc(&var->atom);
|
||||
}
|
||||
|
||||
PJ_DEF(void) pj_atomic_dec(pj_atomic_t *var)
|
||||
{
|
||||
atomic_dec(&var->atom);
|
||||
}
|
||||
|
||||
PJ_DEF(void) pj_atomic_add( pj_atomic_t *var, pj_atomic_value_t value )
|
||||
{
|
||||
atomic_add(value, &var->atom);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
PJ_DEF(pj_status_t) pj_thread_local_alloc(long *index)
|
||||
{
|
||||
if (tls_id >= MAX_TLS_ID)
|
||||
return PJ_ETOOMANY;
|
||||
|
||||
*index = tls_id++;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(void) pj_thread_local_free(long index)
|
||||
{
|
||||
pj_assert(index >= 0 && index < MAX_TLS_ID);
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_thread_local_set(long index, void *value)
|
||||
{
|
||||
pj_assert(index >= 0 && index < MAX_TLS_ID);
|
||||
tls_values[index] = value;
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(void*) pj_thread_local_get(long index)
|
||||
{
|
||||
pj_assert(index >= 0 && index < MAX_TLS_ID);
|
||||
return tls_values[index];
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
PJ_DEF(void) pj_enter_critical_section(void)
|
||||
{
|
||||
spin_lock_irqsave(&critical_section, spinlock_flags);
|
||||
}
|
||||
|
||||
PJ_DEF(void) pj_leave_critical_section(void)
|
||||
{
|
||||
spin_unlock_irqrestore(&critical_section, spinlock_flags);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
PJ_DEF(pj_status_t) pj_mutex_create( pj_pool_t *pool,
|
||||
const char *name,
|
||||
int type,
|
||||
pj_mutex_t **ptr_mutex)
|
||||
{
|
||||
pj_mutex_t *mutex;
|
||||
|
||||
PJ_UNUSED_ARG(name);
|
||||
|
||||
mutex = pj_pool_alloc(pool, sizeof(pj_mutex_t));
|
||||
if (!mutex)
|
||||
return PJ_ENOMEM;
|
||||
|
||||
init_MUTEX(&mutex->sem);
|
||||
|
||||
mutex->recursive = (type == PJ_MUTEX_RECURSE);
|
||||
mutex->owner = NULL;
|
||||
mutex->own_count = 0;
|
||||
|
||||
/* Done. */
|
||||
*ptr_mutex = mutex;
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool, const char *name,
|
||||
pj_mutex_t **mutex )
|
||||
{
|
||||
return pj_mutex_create(pool, name, PJ_MUTEX_SIMPLE, mutex);
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_mutex_create_recursive( pj_pool_t *pool,
|
||||
const char *name,
|
||||
pj_mutex_t **mutex )
|
||||
{
|
||||
return pj_mutex_create( pool, name, PJ_MUTEX_RECURSE, mutex);
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_mutex_lock(pj_mutex_t *mutex)
|
||||
{
|
||||
PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
|
||||
|
||||
if (mutex->recursive) {
|
||||
pj_thread_t *this_thread = pj_thread_this();
|
||||
if (mutex->owner == this_thread) {
|
||||
++mutex->own_count;
|
||||
} else {
|
||||
down(&mutex->sem);
|
||||
pj_assert(mutex->own_count == 0);
|
||||
mutex->owner = this_thread;
|
||||
mutex->own_count = 1;
|
||||
}
|
||||
} else {
|
||||
down(&mutex->sem);
|
||||
}
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_mutex_trylock(pj_mutex_t *mutex)
|
||||
{
|
||||
long rc;
|
||||
|
||||
PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
|
||||
|
||||
if (mutex->recursive) {
|
||||
pj_thread_t *this_thread = pj_thread_this();
|
||||
if (mutex->owner == this_thread) {
|
||||
++mutex->own_count;
|
||||
} else {
|
||||
rc = down_interruptible(&mutex->sem);
|
||||
if (rc != 0)
|
||||
return PJ_RETURN_OS_ERROR(-rc);
|
||||
pj_assert(mutex->own_count == 0);
|
||||
mutex->owner = this_thread;
|
||||
mutex->own_count = 1;
|
||||
}
|
||||
} else {
|
||||
int rc = down_trylock(&mutex->sem);
|
||||
if (rc != 0)
|
||||
return PJ_RETURN_OS_ERROR(-rc);
|
||||
}
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_mutex_unlock(pj_mutex_t *mutex)
|
||||
{
|
||||
PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
|
||||
|
||||
if (mutex->recursive) {
|
||||
pj_thread_t *this_thread = pj_thread_this();
|
||||
if (mutex->owner == this_thread) {
|
||||
pj_assert(mutex->own_count > 0);
|
||||
--mutex->own_count;
|
||||
if (mutex->own_count == 0) {
|
||||
mutex->owner = NULL;
|
||||
up(&mutex->sem);
|
||||
}
|
||||
} else {
|
||||
pj_assert(!"Not owner!");
|
||||
return PJ_EINVALIDOP;
|
||||
}
|
||||
} else {
|
||||
up(&mutex->sem);
|
||||
}
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_mutex_destroy(pj_mutex_t *mutex)
|
||||
{
|
||||
PJ_ASSERT_RETURN(mutex != NULL, PJ_EINVAL);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
#if defined(PJ_DEBUG) && PJ_DEBUG != 0
|
||||
PJ_DEF(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex)
|
||||
{
|
||||
if (mutex->recursive)
|
||||
return mutex->owner == pj_thread_this();
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
#endif /* PJ_DEBUG */
|
||||
|
||||
|
||||
#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
|
||||
|
||||
PJ_DEF(pj_status_t) pj_sem_create( pj_pool_t *pool,
|
||||
const char *name,
|
||||
unsigned initial,
|
||||
unsigned max,
|
||||
pj_sem_t **sem)
|
||||
{
|
||||
pj_sem_t *sem;
|
||||
|
||||
PJ_UNUSED_ARG(max);
|
||||
|
||||
PJ_ASSERT_RETURN(pool && sem, PJ_EINVAL);
|
||||
|
||||
sem = pj_pool_alloc(pool, sizeof(pj_sem_t));
|
||||
sema_init(&sem->sem, initial);
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_sem_wait(pj_sem_t *sem)
|
||||
{
|
||||
PJ_ASSERT_RETURN(pool && sem, PJ_EINVAL);
|
||||
|
||||
down(&sem->sem);
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_sem_trywait(pj_sem_t *sem)
|
||||
{
|
||||
int rc;
|
||||
|
||||
PJ_ASSERT_RETURN(pool && sem, PJ_EINVAL);
|
||||
|
||||
rc = down_trylock(&sem->sem);
|
||||
if (rc != 0) {
|
||||
return PJ_RETURN_OS_ERROR(-rc);
|
||||
} else {
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_sem_post(pj_sem_t *sem)
|
||||
{
|
||||
PJ_ASSERT_RETURN(pool && sem, PJ_EINVAL);
|
||||
|
||||
up(&sem->sem);
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_sem_destroy(pj_sem_t *sem)
|
||||
{
|
||||
PJ_ASSERT_RETURN(pool && sem, PJ_EINVAL);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* PJ_HAS_SEMAPHORE */
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <pj/string.h>
|
||||
#include <pj/compat/errno.h>
|
||||
#include <linux/config.h>
|
||||
#include <linux/version.h>
|
||||
#if defined(MODVERSIONS)
|
||||
#include <linux/modversions.h>
|
||||
#endif
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
int kernel_errno;
|
||||
|
||||
PJ_DEF(pj_status_t) pj_get_os_error(void)
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
PJ_DEF(void) pj_set_os_error(pj_status_t code)
|
||||
{
|
||||
errno = code;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_get_netos_error(void)
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
PJ_DEF(void) pj_set_netos_error(pj_status_t code)
|
||||
{
|
||||
errno = code;
|
||||
}
|
||||
|
||||
/*
|
||||
* platform_strerror()
|
||||
*
|
||||
* Platform specific error message. This file is called by pj_strerror()
|
||||
* in errno.c
|
||||
*/
|
||||
int platform_strerror( pj_os_err_type os_errcode,
|
||||
char *buf, pj_size_t bufsize)
|
||||
{
|
||||
char errmsg[PJ_ERR_MSG_SIZE];
|
||||
int len;
|
||||
|
||||
/* Handle EINVAL as special case so that it'll pass errno test. */
|
||||
if (os_errcode==EINVAL)
|
||||
strcpy(errmsg, "Invalid value");
|
||||
else
|
||||
snprintf(errmsg, sizeof(errmsg), "errno=%d", os_errcode);
|
||||
|
||||
len = strlen(errmsg);
|
||||
|
||||
if (len >= bufsize)
|
||||
len = bufsize-1;
|
||||
|
||||
pj_memcpy(buf, errmsg, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <pj/os.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PJ_DEF(pj_status_t) pj_gettimeofday(pj_time_val *tv)
|
||||
{
|
||||
struct timeval tval;
|
||||
|
||||
do_gettimeofday(&tval);
|
||||
tv->sec = tval.tv_sec;
|
||||
tv->msec = tval.tv_usec / 1000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_time_decode(const pj_time_val *tv, pj_parsed_time *pt)
|
||||
{
|
||||
pt->year = 2005;
|
||||
pt->mon = 8;
|
||||
pt->day = 20;
|
||||
pt->hour = 16;
|
||||
pt->min = 30;
|
||||
pt->sec = 30;
|
||||
pt->wday = 3;
|
||||
pt->yday = 200;
|
||||
pt->msec = 777;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode parsed time to time value.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_time_encode(const pj_parsed_time *pt, pj_time_val *tv);
|
||||
|
||||
/**
|
||||
* Convert local time to GMT.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_time_local_to_gmt(pj_time_val *tv);
|
||||
|
||||
/**
|
||||
* Convert GMT to local time.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_time_gmt_to_local(pj_time_val *tv);
|
||||
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <pj/os.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
#if 0
|
||||
PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts)
|
||||
{
|
||||
ts->u32.hi = 0;
|
||||
ts->u32.lo = jiffies;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq)
|
||||
{
|
||||
freq->u32.hi = 0;
|
||||
freq->u32.lo = HZ;
|
||||
return 0;
|
||||
}
|
||||
#elif 0
|
||||
PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts)
|
||||
{
|
||||
struct timespec tv;
|
||||
|
||||
tv = CURRENT_TIME;
|
||||
|
||||
ts->u64 = tv.tv_sec;
|
||||
ts->u64 *= NSEC_PER_SEC;
|
||||
ts->u64 += tv.tv_nsec;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq)
|
||||
{
|
||||
freq->u32.hi = 0;
|
||||
freq->u32.lo = NSEC_PER_SEC;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
do_gettimeofday(&tv);
|
||||
|
||||
ts->u64 = tv.tv_sec;
|
||||
ts->u64 *= USEC_PER_SEC;
|
||||
ts->u64 += tv.tv_usec;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq)
|
||||
{
|
||||
freq->u32.hi = 0;
|
||||
freq->u32.lo = USEC_PER_SEC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -229,7 +229,7 @@ PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong)
|
|||
*/
|
||||
PJ_DEF(char*) pj_inet_ntoa(pj_in_addr inaddr)
|
||||
{
|
||||
#if 0 //!defined(PJ_LINUX) && !defined(PJ_LINUX_KERNEL)
|
||||
#if 0
|
||||
return inet_ntoa(*(struct in_addr*)&inaddr);
|
||||
#else
|
||||
struct in_addr addr;
|
||||
|
|
|
@ -1,785 +0,0 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <pj/sock.h>
|
||||
#include <pj/assert.h>
|
||||
#include <pj/string.h> /* pj_memcpy() */
|
||||
#include <pj/os.h> /* PJ_CHECK_STACK() */
|
||||
#include <pj/addr_resolv.h> /* pj_gethostbyname() */
|
||||
#include <pj/ctype.h>
|
||||
#include <pj/compat/sprintf.h>
|
||||
#include <pj/log.h>
|
||||
#include <pj/errno.h>
|
||||
|
||||
/* Linux kernel specific. */
|
||||
#include <linux/socket.h>
|
||||
#include <linux/net.h>
|
||||
//#include <net/sock.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/syscalls.h> /* sys_xxx() */
|
||||
#include <asm/ioctls.h> /* FIONBIO */
|
||||
#include <linux/utsname.h> /* for pj_gethostname() */
|
||||
|
||||
#define THIS_FILE "sock_linux_kernel.c"
|
||||
|
||||
/*
|
||||
* Address families conversion.
|
||||
* The values here are indexed based on pj_addr_family-0xFF00.
|
||||
*/
|
||||
const pj_uint16_t PJ_AF_UNIX = AF_UNIX;
|
||||
const pj_uint16_t PJ_AF_INET = AF_INET;
|
||||
const pj_uint16_t PJ_AF_INET6 = AF_INET6;
|
||||
#ifdef AF_PACKET
|
||||
const pj_uint16_t PJ_AF_PACKET = AF_PACKET;
|
||||
#else
|
||||
# error "AF_PACKET undeclared!"
|
||||
#endif
|
||||
#ifdef AF_IRDA
|
||||
const pj_uint16_t PJ_AF_IRDA = AF_IRDA;
|
||||
#else
|
||||
# error "AF_IRDA undeclared!"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Socket types conversion.
|
||||
* The values here are indexed based on pj_sock_type-0xFF00
|
||||
*/
|
||||
const pj_uint16_t PJ_SOCK_STREAM= SOCK_STREAM;
|
||||
const pj_uint16_t PJ_SOCK_DGRAM = SOCK_DGRAM;
|
||||
const pj_uint16_t PJ_SOCK_RAW = SOCK_RAW;
|
||||
const pj_uint16_t PJ_SOCK_RDM = SOCK_RDM;
|
||||
|
||||
/*
|
||||
* Socket level values.
|
||||
*/
|
||||
const pj_uint16_t PJ_SOL_SOCKET = SOL_SOCKET;
|
||||
#ifdef SOL_IP
|
||||
const pj_uint16_t PJ_SOL_IP = SOL_IP;
|
||||
#else
|
||||
# error "SOL_IP undeclared!"
|
||||
#endif /* SOL_IP */
|
||||
#if defined(SOL_TCP)
|
||||
const pj_uint16_t PJ_SOL_TCP = SOL_TCP;
|
||||
#else
|
||||
# error "SOL_TCP undeclared!"
|
||||
#endif /* SOL_TCP */
|
||||
#ifdef SOL_UDP
|
||||
const pj_uint16_t PJ_SOL_UDP = SOL_UDP;
|
||||
#else
|
||||
# error "SOL_UDP undeclared!"
|
||||
#endif
|
||||
#ifdef SOL_IPV6
|
||||
const pj_uint16_t PJ_SOL_IPV6 = SOL_IPV6;
|
||||
#else
|
||||
# error "SOL_IPV6 undeclared!"
|
||||
#endif
|
||||
|
||||
/* optname values. */
|
||||
const pj_uint16_t PJ_SO_TYPE = SO_TYPE;
|
||||
const pj_uint16_t PJ_SO_RCVBUF = SO_RCVBUF;
|
||||
const pj_uint16_t PJ_SO_SNDBUF = SO_SNDBUF;
|
||||
|
||||
/*
|
||||
* Convert 16-bit value from network byte order to host byte order.
|
||||
*/
|
||||
PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort)
|
||||
{
|
||||
return ntohs(netshort);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert 16-bit value from host byte order to network byte order.
|
||||
*/
|
||||
PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort)
|
||||
{
|
||||
return htons(hostshort);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert 32-bit value from network byte order to host byte order.
|
||||
*/
|
||||
PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong)
|
||||
{
|
||||
return ntohl(netlong);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert 32-bit value from host byte order to network byte order.
|
||||
*/
|
||||
PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong)
|
||||
{
|
||||
return htonl(hostlong);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an Internet host address given in network byte order
|
||||
* to string in standard numbers and dots notation.
|
||||
*/
|
||||
PJ_DEF(char*) pj_inet_ntoa(pj_in_addr in)
|
||||
{
|
||||
#define UC(b) (((int)b)&0xff)
|
||||
static char b[18];
|
||||
char *p;
|
||||
|
||||
p = (char *)∈
|
||||
pj_snprintf(b, sizeof(b), "%d.%d.%d.%d",
|
||||
UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function converts the Internet host address ccp from the standard
|
||||
* numbers-and-dots notation into binary data and stores it in the structure
|
||||
* that inp points to.
|
||||
*/
|
||||
PJ_DEF(int) pj_inet_aton(const pj_str_t *ccp, struct pj_in_addr *addr)
|
||||
{
|
||||
pj_uint32_t val;
|
||||
int base, n;
|
||||
char c;
|
||||
unsigned parts[4];
|
||||
unsigned *pp = parts;
|
||||
char cp_copy[18];
|
||||
char *cp = cp_copy;
|
||||
|
||||
addr->s_addr = PJ_INADDR_NONE;
|
||||
|
||||
if (ccp->slen > 15) return 0;
|
||||
|
||||
pj_memcpy(cp, ccp->ptr, ccp->slen);
|
||||
cp[ccp->slen] = '\0';
|
||||
|
||||
c = *cp;
|
||||
for (;;) {
|
||||
/*
|
||||
* Collect number up to ``.''.
|
||||
* Values are specified as for C:
|
||||
* 0x=hex, 0=octal, isdigit=decimal.
|
||||
*/
|
||||
if (!pj_isdigit((int)c))
|
||||
return (0);
|
||||
val = 0; base = 10;
|
||||
if (c == '0') {
|
||||
c = *++cp;
|
||||
if (c == 'x' || c == 'X')
|
||||
base = 16, c = *++cp;
|
||||
else
|
||||
base = 8;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (pj_isascii((int)c) && pj_isdigit((int)c)) {
|
||||
val = (val * base) + (c - '0');
|
||||
c = *++cp;
|
||||
} else if (base==16 && pj_isascii((int)c) && pj_isxdigit((int)c)) {
|
||||
val = (val << 4) |
|
||||
(c + 10 - (pj_islower((int)c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '.') {
|
||||
/*
|
||||
* Internet format:
|
||||
* a.b.c.d
|
||||
* a.b.c (with c treated as 16 bits)
|
||||
* a.b (with b treated as 24 bits)
|
||||
*/
|
||||
if (pp >= parts + 3)
|
||||
return (0);
|
||||
*pp++ = val;
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for trailing characters.
|
||||
*/
|
||||
if (c != '\0' && (!pj_isascii((int)c) || !pj_isspace((int)c)))
|
||||
return (0);
|
||||
/*
|
||||
* Concoct the address according to
|
||||
* the number of parts specified.
|
||||
*/
|
||||
n = pp - parts + 1;
|
||||
switch (n) {
|
||||
case 0:
|
||||
return (0); /* initial nondigit */
|
||||
case 1: /* a -- 32 bits */
|
||||
break;
|
||||
case 2: /* a.b -- 8.24 bits */
|
||||
if (val > 0xffffff)
|
||||
return (0);
|
||||
val |= parts[0] << 24;
|
||||
break;
|
||||
case 3: /* a.b.c -- 8.8.16 bits */
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16);
|
||||
break;
|
||||
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
||||
if (val > 0xff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
||||
break;
|
||||
}
|
||||
|
||||
if (addr)
|
||||
addr->s_addr = pj_htonl(val);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert address string with numbers and dots to binary IP address.
|
||||
*/
|
||||
PJ_DEF(pj_in_addr) pj_inet_addr(const pj_str_t *cp)
|
||||
{
|
||||
pj_in_addr addr;
|
||||
pj_inet_aton(cp, &addr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the IP address of an IP socket address from string address,
|
||||
* with resolving the host if necessary. The string address may be in a
|
||||
* standard numbers and dots notation or may be a hostname. If hostname
|
||||
* is specified, then the function will resolve the host into the IP
|
||||
* address.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sockaddr_in_set_str_addr( pj_sockaddr_in *addr,
|
||||
const pj_str_t *str_addr)
|
||||
{
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
pj_assert(str_addr && str_addr->slen < PJ_MAX_HOSTNAME);
|
||||
|
||||
addr->sin_family = AF_INET;
|
||||
|
||||
if (str_addr && str_addr->slen) {
|
||||
addr->sin_addr = pj_inet_addr(str_addr);
|
||||
if (addr->sin_addr.s_addr == PJ_INADDR_NONE) {
|
||||
pj_hostent he;
|
||||
if (pj_gethostbyname(str_addr, &he) == 0) {
|
||||
addr->sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;
|
||||
} else {
|
||||
addr->sin_addr.s_addr = PJ_INADDR_NONE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
addr->sin_addr.s_addr = 0;
|
||||
}
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the IP address and port of an IP socket address.
|
||||
* The string address may be in a standard numbers and dots notation or
|
||||
* may be a hostname. If hostname is specified, then the function will
|
||||
* resolve the host into the IP address.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sockaddr_in_init( pj_sockaddr_in *addr,
|
||||
const pj_str_t *str_addr,
|
||||
pj_uint16_t port)
|
||||
{
|
||||
pj_assert(addr && str_addr);
|
||||
|
||||
addr->sin_family = PJ_AF_INET;
|
||||
pj_sockaddr_in_set_port(addr, port);
|
||||
return pj_sockaddr_in_set_str_addr(addr, str_addr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get hostname.
|
||||
*/
|
||||
PJ_DEF(const pj_str_t*) pj_gethostname(void)
|
||||
{
|
||||
static char buf[PJ_MAX_HOSTNAME];
|
||||
static pj_str_t hostname;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
if (hostname.ptr == NULL) {
|
||||
hostname.ptr = buf;
|
||||
down_read(&uts_sem);
|
||||
hostname.slen = strlen(system_utsname.nodename);
|
||||
if (hostname.slen > PJ_MAX_HOSTNAME) {
|
||||
hostname.ptr[0] = '\0';
|
||||
hostname.slen = 0;
|
||||
} else {
|
||||
pj_memcpy(hostname.ptr, system_utsname.nodename, hostname.slen);
|
||||
}
|
||||
up_read(&uts_sem);
|
||||
}
|
||||
return &hostname;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get first IP address associated with the hostname.
|
||||
*/
|
||||
PJ_DEF(pj_in_addr) pj_gethostaddr(void)
|
||||
{
|
||||
pj_sockaddr_in addr;
|
||||
const pj_str_t *hostname = pj_gethostname();
|
||||
|
||||
pj_sockaddr_in_set_str_addr(&addr, hostname);
|
||||
return addr.sin_addr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create new socket/endpoint for communication and returns a descriptor.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_socket(int af, int type, int proto,
|
||||
pj_sock_t *sock_fd)
|
||||
{
|
||||
long result;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
/* Sanity checks. */
|
||||
PJ_ASSERT_RETURN(PJ_INVALID_SOCKET == -1 && sock_fd != NULL, PJ_EINVAL);
|
||||
|
||||
/* Initialize returned socket */
|
||||
*sock_fd = PJ_INVALID_SOCKET;
|
||||
|
||||
/* Create socket. */
|
||||
result = sys_socket(af, type, proto);
|
||||
if (result < 0) {
|
||||
return PJ_RETURN_OS_ERROR((-result));
|
||||
}
|
||||
|
||||
*sock_fd = result;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bind socket.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sockfd,
|
||||
const pj_sockaddr_t *addr,
|
||||
int len)
|
||||
{
|
||||
long err;
|
||||
mm_segment_t oldfs;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
PJ_ASSERT_RETURN(addr!=NULL && len >= sizeof(struct pj_sockaddr),
|
||||
PJ_EINVAL);
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
err = sys_bind(sockfd, (struct sockaddr*)addr, len);
|
||||
|
||||
set_fs(oldfs);
|
||||
|
||||
if (err)
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
else
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Bind socket.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_bind_in( pj_sock_t sockfd,
|
||||
pj_uint32_t addr32,
|
||||
pj_uint16_t port)
|
||||
{
|
||||
pj_sockaddr_in addr;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
addr.sin_family = PJ_AF_INET;
|
||||
addr.sin_addr.s_addr = pj_htonl(addr32);
|
||||
addr.sin_port = pj_htons(port);
|
||||
|
||||
return pj_sock_bind(sockfd, &addr, sizeof(pj_sockaddr_in));
|
||||
}
|
||||
|
||||
/*
|
||||
* Close socket.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_close(pj_sock_t sockfd)
|
||||
{
|
||||
long err;
|
||||
|
||||
err = sys_close(sockfd);
|
||||
|
||||
if (err != 0)
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
else
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get remote's name.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_getpeername( pj_sock_t sockfd,
|
||||
pj_sockaddr_t *addr,
|
||||
int *namelen)
|
||||
{
|
||||
mm_segment_t oldfs;
|
||||
long err;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
err = sys_getpeername( sockfd, addr, namelen);
|
||||
|
||||
set_fs(oldfs);
|
||||
|
||||
if (err)
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
else
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get socket name.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sockfd,
|
||||
pj_sockaddr_t *addr,
|
||||
int *namelen)
|
||||
{
|
||||
mm_segment_t oldfs;
|
||||
int err;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
err = sys_getsockname( sockfd, addr, namelen );
|
||||
|
||||
set_fs(oldfs);
|
||||
|
||||
if (err)
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
else
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send data
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_send( pj_sock_t sockfd,
|
||||
const void *buf,
|
||||
pj_ssize_t *len,
|
||||
unsigned flags)
|
||||
{
|
||||
return pj_sock_sendto(sockfd, buf, len, flags, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send data.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_sendto( pj_sock_t sockfd,
|
||||
const void *buff,
|
||||
pj_ssize_t *len,
|
||||
unsigned flags,
|
||||
const pj_sockaddr_t *addr,
|
||||
int addr_len)
|
||||
{
|
||||
long err;
|
||||
mm_segment_t oldfs;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
err = *len = sys_sendto( sockfd, (void*)buff, *len, flags,
|
||||
(void*)addr, addr_len );
|
||||
|
||||
set_fs(oldfs);
|
||||
|
||||
if (err >= 0) {
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
else {
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive data.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_recv( pj_sock_t sockfd,
|
||||
void *buf,
|
||||
pj_ssize_t *len,
|
||||
unsigned flags)
|
||||
{
|
||||
return pj_sock_recvfrom(sockfd, buf, len, flags, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive data.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_recvfrom( pj_sock_t sockfd,
|
||||
void *buff,
|
||||
pj_ssize_t *size,
|
||||
unsigned flags,
|
||||
pj_sockaddr_t *from,
|
||||
int *fromlen)
|
||||
{
|
||||
mm_segment_t oldfs;
|
||||
long err;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
err = *size = sys_recvfrom( sockfd, buff, *size, flags, from, fromlen);
|
||||
|
||||
set_fs(oldfs);
|
||||
|
||||
if (err >= 0) {
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
else {
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get socket option.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_getsockopt( pj_sock_t sockfd,
|
||||
pj_uint16_t level,
|
||||
pj_uint16_t optname,
|
||||
void *optval,
|
||||
int *optlen)
|
||||
{
|
||||
mm_segment_t oldfs;
|
||||
long err;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
err = sys_getsockopt( sockfd, level, optname, optval, optlen);
|
||||
|
||||
set_fs(oldfs);
|
||||
|
||||
if (err)
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
else
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set socket option.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sockfd,
|
||||
pj_uint16_t level,
|
||||
pj_uint16_t optname,
|
||||
const void *optval,
|
||||
int optlen)
|
||||
{
|
||||
long err;
|
||||
mm_segment_t oldfs;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
err = sys_setsockopt( sockfd, level, optname, (void*)optval, optlen);
|
||||
|
||||
set_fs(oldfs);
|
||||
|
||||
if (err)
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
else
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set socket option.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_setsockopt_params( pj_sock_t sockfd,
|
||||
const pj_sockopt_params *params)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
pj_status_t retval = PJ_SUCCESS;
|
||||
PJ_CHECK_STACK();
|
||||
PJ_ASSERT_RETURN(params, PJ_EINVAL);
|
||||
|
||||
for (;i<params->cnt && i<PJ_MAX_SOCKOPT_PARAMS;++i) {
|
||||
pj_status_t status = pj_sock_setsockopt(sockfd,
|
||||
params->options[i].level,
|
||||
params->options[i].optname,
|
||||
params->options[i].optval,
|
||||
params->options[i].optlen);
|
||||
if (status != PJ_SUCCESS) {
|
||||
retval = status;
|
||||
PJ_PERROR(4,(THIS_FILE, status,
|
||||
"Warning: error applying sock opt %d",
|
||||
params->options[i].optname));
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdown socket.
|
||||
*/
|
||||
#if PJ_HAS_TCP
|
||||
PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sockfd,
|
||||
int how)
|
||||
{
|
||||
long err;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
err = sys_shutdown(sockfd, how);
|
||||
|
||||
if (err)
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
else
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start listening to incoming connections.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sockfd,
|
||||
int backlog)
|
||||
{
|
||||
long err;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
err = sys_listen( sockfd, backlog );
|
||||
|
||||
if (err)
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
else
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connect socket.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sockfd,
|
||||
const pj_sockaddr_t *addr,
|
||||
int namelen)
|
||||
{
|
||||
long err;
|
||||
mm_segment_t oldfs;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
err = sys_connect( sockfd, (void*)addr, namelen );
|
||||
|
||||
set_fs(oldfs);
|
||||
|
||||
if (err)
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
else
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accept incoming connections
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t sockfd,
|
||||
pj_sock_t *newsockfd,
|
||||
pj_sockaddr_t *addr,
|
||||
int *addrlen)
|
||||
{
|
||||
long err;
|
||||
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
PJ_ASSERT_RETURN(newsockfd != NULL, PJ_EINVAL);
|
||||
|
||||
err = sys_accept( sockfd, addr, addrlen);
|
||||
|
||||
if (err < 0) {
|
||||
*newsockfd = PJ_INVALID_SOCKET;
|
||||
return PJ_RETURN_OS_ERROR(-err);
|
||||
}
|
||||
else {
|
||||
*newsockfd = err;
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
}
|
||||
#endif /* PJ_HAS_TCP */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Permission to steal inet_ntoa() and inet_aton() as long as this notice below
|
||||
* is included:
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue