⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ptio.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//*  * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape Portable Runtime (NSPR). *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//*** File:   ptio.c** Descritpion:  Implemenation of I/O methods for pthreads*/#if defined(_PR_PTHREADS)#if defined(_PR_POLL_WITH_SELECT)/* set fd limit for select(), before including system header files */#define FD_SETSIZE (16 * 1024)#endif#include <pthread.h>#include <string.h>  /* for memset() */#include <sys/types.h>#include <dirent.h>#include <fcntl.h>#include <unistd.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/uio.h>#include <sys/file.h>#include <sys/ioctl.h>#if defined(SOLARIS) || defined(UNIXWARE)#include <sys/filio.h>  /* to pick up FIONREAD */#endif#ifdef _PR_POLL_AVAILABLE#include <poll.h>#endif#ifdef AIX/* To pick up sysconf() */#include <unistd.h>#include <dlfcn.h>  /* for dlopen */#else/* To pick up getrlimit() etc. */#include <sys/time.h>#include <sys/resource.h>#endif#ifdef SOLARIS/* * Define HAVE_SENDFILEV if the system has the sendfilev() system call. * Code built this way won't run on a system without sendfilev(). * We can define HAVE_SENDFILEV by default when the minimum release * of Solaris that NSPR supports has sendfilev(). */#ifdef HAVE_SENDFILEV#include <sys/sendfile.h>#define SOLARIS_SENDFILEV(a, b, c, d) sendfilev((a), (b), (c), (d))#else#include <dlfcn.h>  /* for dlopen *//* * Match the definitions in <sys/sendfile.h>. */typedef struct sendfilevec {    int sfv_fd;       /* input fd */    uint_t sfv_flag;  /* flags */    off_t sfv_off;    /* offset to start reading from */    size_t sfv_len;   /* amount of data */} sendfilevec_t;#define SFV_FD_SELF (-2)/* * extern ssize_t sendfilev(int, const struct sendfilevec *, int, size_t *); */static ssize_t (*pt_solaris_sendfilev_fptr)() = NULL;#define SOLARIS_SENDFILEV(a, b, c, d) \        (*pt_solaris_sendfilev_fptr)((a), (b), (c), (d))#endif /* HAVE_SENDFILEV */#endif /* SOLARIS *//* * The send_file() system call is available in AIX 4.3.2 or later. * If this file is compiled on an older AIX system, it attempts to * look up the send_file symbol at run time to determine whether * we can use the faster PR_SendFile/PR_TransmitFile implementation based on * send_file().  On AIX 4.3.2 or later, we can safely skip this * runtime function dispatching and just use the send_file based * implementation. */#ifdef AIX#ifdef SF_CLOSE#define HAVE_SEND_FILE#endif#ifdef HAVE_SEND_FILE#define AIX_SEND_FILE(a, b, c) send_file(a, b, c)#else /* HAVE_SEND_FILE *//* * The following definitions match those in <sys/socket.h> * on AIX 4.3.2. *//* * Structure for the send_file() system call */struct sf_parms {    /* --------- header parms ---------- */    void      *header_data;         /* Input/Output. Points to header buf */    uint_t    header_length;        /* Input/Output. Length of the header */    /* --------- file parms ------------ */    int       file_descriptor;      /* Input. File descriptor of the file */    unsigned long long file_size;   /* Output. Size of the file */    unsigned long long file_offset; /* Input/Output. Starting offset */    long long file_bytes;           /* Input/Output. no. of bytes to send */    /* --------- trailer parms --------- */    void      *trailer_data;        /* Input/Output. Points to trailer buf */    uint_t    trailer_length;       /* Input/Output. Length of the trailer */    /* --------- return info ----------- */    unsigned long long bytes_sent;  /* Output. no. of bytes sent */};/* * Flags for the send_file() system call */#define SF_CLOSE        0x00000001      /* close the socket after completion */#define SF_REUSE        0x00000002      /* reuse socket. not supported */#define SF_DONT_CACHE   0x00000004      /* don't apply network buffer cache */#define SF_SYNC_CACHE   0x00000008      /* sync/update network buffer cache *//* * prototype: size_t send_file(int *, struct sf_parms *, uint_t); */static ssize_t (*pt_aix_sendfile_fptr)() = NULL;#define AIX_SEND_FILE(a, b, c) (*pt_aix_sendfile_fptr)(a, b, c)#endif /* HAVE_SEND_FILE */#endif /* AIX */#ifdef LINUX#include <sys/sendfile.h>#endif#include "primpl.h"#include <netinet/tcp.h>  /* TCP_NODELAY, TCP_MAXSEG */#ifdef LINUX/* TCP_CORK is not defined in <netinet/tcp.h> on Red Hat Linux 6.0 */#ifndef TCP_CORK#define TCP_CORK 3#endif#endif#if defined(SOLARIS)#define _PRSockOptVal_t char *#elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(HPUX) \    || defined(LINUX) || defined(FREEBSD) || defined(BSDI) || defined(VMS) \    || defined(NTO) || defined(OPENBSD) || defined(DARWIN) \    || defined(UNIXWARE)#define _PRSockOptVal_t void *#else#error "Cannot determine architecture"#endif#if (defined(HPUX) && !defined(HPUX10_30) && !defined(HPUX11))#define _PRSelectFdSetArg_t int *#elif defined(AIX4_1)#define _PRSelectFdSetArg_t void *#elif defined(IRIX) || (defined(AIX) && !defined(AIX4_1)) \    || defined(OSF1) || defined(SOLARIS) \    || defined(HPUX10_30) || defined(HPUX11) || defined(LINUX) \    || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \    || defined(BSDI) || defined(VMS) || defined(NTO) || defined(DARWIN) \    || defined(UNIXWARE)#define _PRSelectFdSetArg_t fd_set *#else#error "Cannot determine architecture"#endifstatic PRFileDesc *pt_SetMethods(    PRIntn osfd, PRDescType type, PRBool isAcceptedSocket, PRBool imported);static PRLock *_pr_flock_lock;  /* For PR_LockFile() etc. */static PRCondVar *_pr_flock_cv;  /* For PR_LockFile() etc. */static PRLock *_pr_rename_lock;  /* For PR_Rename() *//**************************************************************************//* These two functions are only used in assertions. */#if defined(DEBUG)PRBool IsValidNetAddr(const PRNetAddr *addr){    if ((addr != NULL)            && (addr->raw.family != AF_UNIX)            && (addr->raw.family != PR_AF_INET6)            && (addr->raw.family != AF_INET)) {        return PR_FALSE;    }    return PR_TRUE;}static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len){    /*     * The definition of the length of a Unix domain socket address     * is not uniform, so we don't check it.     */    if ((addr != NULL)            && (addr->raw.family != AF_UNIX)            && (PR_NETADDR_SIZE(addr) != addr_len)) {#if defined(LINUX) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 1        /*         * In glibc 2.1, struct sockaddr_in6 is 24 bytes.  In glibc 2.2         * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id         * field and is 28 bytes.  It is possible for socket functions         * to return an addr_len greater than sizeof(struct sockaddr_in6).         * We need to allow that.  (Bugzilla bug #77264)         */        if ((PR_AF_INET6 == addr->raw.family)                && (sizeof(addr->ipv6) == addr_len)) {            return PR_TRUE;        }#endif        return PR_FALSE;    }    return PR_TRUE;}#endif /* DEBUG *//*****************************************************************************//************************* I/O Continuation machinery ************************//*****************************************************************************//* * The polling interval defines the maximum amount of time that a thread * might hang up before an interrupt is noticed. */#define PT_DEFAULT_POLL_MSEC 5000#if defined(_PR_POLL_WITH_SELECT)#define PT_DEFAULT_SELECT_SEC (PT_DEFAULT_POLL_MSEC/PR_MSEC_PER_SEC)#define PT_DEFAULT_SELECT_USEC							\		((PT_DEFAULT_POLL_MSEC % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC)#endif/* * pt_SockLen is the type for the length of a socket address * structure, used in the address length argument to bind, * connect, accept, getsockname, getpeername, etc.  Posix.1g * defines this type as socklen_t.  It is size_t or int on * most current systems. */#if defined(HAVE_SOCKLEN_T) \    || (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2)typedef socklen_t pt_SockLen;#elif (defined(AIX) && !defined(AIX4_1)) \    || defined(VMS)typedef PRSize pt_SockLen;#elsetypedef PRIntn pt_SockLen;#endiftypedef struct pt_Continuation pt_Continuation;typedef PRBool (*ContinuationFn)(pt_Continuation *op, PRInt16 revents);typedef enum pr_ContuationStatus{    pt_continuation_pending,    pt_continuation_done} pr_ContuationStatus;struct pt_Continuation{    /* The building of the continuation operation */    ContinuationFn function;                /* what function to continue */    union { PRIntn osfd; } arg1;            /* #1 - the op's fd */    union { void* buffer; } arg2;           /* #2 - primary transfer buffer */    union {        PRSize amount;                      /* #3 - size of 'buffer', or */        pt_SockLen *addr_len;                  /*    - length of address */#ifdef HPUX11        /*         * For sendfile()         */		struct file_spec {		        	off_t offset;                       /* offset in file to send */        	size_t nbytes;                      /* length of file data to send */        	size_t st_size;                     /* file size */		} file_spec;#endif    } arg3;    union { PRIntn flags; } arg4;           /* #4 - read/write flags */    union { PRNetAddr *addr; } arg5;        /* #5 - send/recv address */#ifdef HPUX11    /*     * For sendfile()     */    int filedesc;                           /* descriptor of file to send */    int nbytes_to_send;                     /* size of header and file */#endif  /* HPUX11 */    #ifdef SOLARIS    /*     * For sendfilev()     */    int nbytes_to_send;                     /* size of header and file */#endif  /* SOLARIS */#ifdef LINUX    /*     * For sendfile()     */    int in_fd;                              /* descriptor of file to send */    off_t offset;    size_t count;#endif  /* LINUX */     PRIntervalTime timeout;                 /* client (relative) timeout */    PRInt16 event;                           /* flags for poll()'s events */    /*    ** The representation and notification of the results of the operation.    ** These function can either return an int return code or a pointer to    ** some object.    */    union { PRSize code; void *object; } result;    PRIntn syserrno;                        /* in case it failed, why (errno) */    pr_ContuationStatus status;             /* the status of the operation */};#if defined(DEBUG)PTDebug pt_debug;  /* this is shared between several modules */PR_IMPLEMENT(void) PT_GetStats(PTDebug* here) { *here = pt_debug; }PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg){    PTDebug stats;    char buffer[100];    PRExplodedTime tod;    PRInt64 elapsed, aMil;    PT_GetStats(&stats);  /* a copy */    PR_ExplodeTime(stats.timeStarted, PR_LocalTimeParameters, &tod);    (void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod);    LL_SUB(elapsed, PR_Now(), stats.timeStarted);    LL_I2L(aMil, 1000000);    LL_DIV(elapsed, elapsed, aMil);        if (NULL != msg) PR_fprintf(debug_out, "%s", msg);    PR_fprintf(        debug_out, "\tstarted: %s[%lld]\n", buffer, elapsed);    PR_fprintf(        debug_out, "\tlocks [created: %u, destroyed: %u]\n",        stats.locks_created, stats.locks_destroyed);    PR_fprintf(        debug_out, "\tlocks [acquired: %u, released: %u]\n",        stats.locks_acquired, stats.locks_released);    PR_fprintf(        debug_out, "\tcvars [created: %u, destroyed: %u]\n",        stats.cvars_created, stats.cvars_destroyed);    PR_fprintf(        debug_out, "\tcvars [notified: %u, delayed_delete: %u]\n",        stats.cvars_notified, stats.delayed_cv_deletes);}  /* PT_FPrintStats */#endif  /* DEBUG */#if defined(_PR_POLL_WITH_SELECT)/* * OSF1 and HPUX report the POLLHUP event for a socket when the * shutdown(SHUT_WR) operation is called for the remote end, even though * the socket is still writeable. Use select(), instead of poll(), to * workaround this problem. */static void pt_poll_now_with_select(pt_Continuation *op){    PRInt32 msecs;	fd_set rd, wr, *rdp, *wrp;	struct timeval tv;	PRIntervalTime epoch, now, elapsed, remaining;	PRBool wait_for_remaining;    PRThread *self = PR_GetCurrentThread();    	PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout);	PR_ASSERT(op->arg1.osfd < FD_SETSIZE);    switch (op->timeout) {        case PR_INTERVAL_NO_TIMEOUT:			tv.tv_sec = PT_DEFAULT_SELECT_SEC;			tv.tv_usec = PT_DEFAULT_SELECT_USEC;			do			{				PRIntn rv;				if (op->event & POLLIN) {					FD_ZERO(&rd);					FD_SET(op->arg1.osfd, &rd);					rdp = &rd;				} else					rdp = NULL;				if (op->event & POLLOUT) {					FD_ZERO(&wr);					FD_SET(op->arg1.osfd, &wr);					wrp = &wr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -