source: rtems/c/src/libnetworking/sys/socketvar.h @ a6f3cff

4.104.114.84.95
Last change on this file since a6f3cff was a6f3cff, checked in by Joel Sherrill <joel.sherrill@…>, on 06/11/99 at 14:11:44

Patch from Ian Lance Taylor <ian@…>:

The select function is not particularly efficient when dealing with a
large number of sockets. The application has to build a big set of
bits and pass it in. RTEMS has to look through all those bits and see
what is ready. Then the application has to look through all the bits
again.

On the other hand, when using RTEMS, the select function is needed
exactly when you have a large number of sockets, because that is when
it becomes prohibitive to use a separate thread for each socket.

I think it would make more sense for RTEMS to support callback
functions which could be invoked when there is data available to read
from a socket, or when there is space available to write to a socket.

Accordingly, I implemented them.

This patch adds two new SOL_SOCKET options to setsockopt and
getsockopt: SO_SNDWAKEUP and SO_RCVWAKEUP. They take arguments of
type struct sockwakeup:

struct sockwakeup {

void (*sw_pfn) P((struct socket *, caddr_t));
caddr_t sw_arg;

};

They are used to add or remove a function which will be called when
something happens for the socket. Getting a callback doesn't imply
that a read or write will succeed, but it does imply that it is worth
trying.

This adds functionality to RTEMS which is somewhat like interrupt
driven socket I/O on Unix.

After the patch to RTEMS, I have appended a patch to
netdemos-19990407/select/test.c to test the new functionality and
demonstrate one way it might be used. To run the new test instead of
the select test, change doSocket to call echoServer2 instead of
echoServer.

  • Property mode set to 100644
File size: 11.1 KB
Line 
1/*-
2 * Copyright (c) 1982, 1986, 1990, 1993
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the University of
16 *      California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *      @(#)socketvar.h 8.3 (Berkeley) 2/19/95
34 * $Id$
35 */
36
37#ifndef _SYS_SOCKETVAR_H_
38#define _SYS_SOCKETVAR_H_
39
40#include <sys/queue.h>                  /* for TAILQ macros */
41#include <sys/select.h>                 /* for struct selinfo */
42
43/*
44 * Kernel structure per socket.
45 * Contains send and receive buffer queues,
46 * handle on protocol and pointer to protocol
47 * private data and error information.
48 */
49struct socket {
50        short   so_type;                /* generic type, see socket.h */
51        short   so_options;             /* from socket call, see socket.h */
52        short   so_linger;              /* time to linger while closing */
53        short   so_state;               /* internal state flags SS_*, below */
54        caddr_t so_pcb;                 /* protocol control block */
55        struct  protosw *so_proto;      /* protocol handle */
56/*
57 * Variables for connection queuing.
58 * Socket where accepts occur is so_head in all subsidiary sockets.
59 * If so_head is 0, socket is not related to an accept.
60 * For head socket so_q0 queues partially completed connections,
61 * while so_q is a queue of connections ready to be accepted.
62 * If a connection is aborted and it has so_head set, then
63 * it has to be pulled out of either so_q0 or so_q.
64 * We allow connections to queue up based on current queue lengths
65 * and limit on number of queued connections for this socket.
66 */
67        struct  socket *so_head;        /* back pointer to accept socket */
68        TAILQ_HEAD(, socket) so_incomp; /* queue of partial unaccepted connections */
69        TAILQ_HEAD(, socket) so_comp;   /* queue of complete unaccepted connections */
70        TAILQ_ENTRY(socket) so_list;    /* list of unaccepted connections */
71        short   so_qlen;                /* number of unaccepted connections */
72        short   so_incqlen;             /* number of unaccepted incomplete
73                                           connections */
74        short   so_qlimit;              /* max number queued connections */
75        u_long  so_timeo;               /* connection timeout */
76        u_short so_error;               /* error affecting connection */
77        pid_t   so_pgid;                /* pgid for signals */
78        u_long  so_oobmark;             /* chars to oob mark */
79/*
80 * Variables for socket buffering.
81 */
82        struct  sockbuf {
83                u_long  sb_cc;          /* actual chars in buffer */
84                u_long  sb_hiwat;       /* max actual char count */
85                u_long  sb_mbcnt;       /* chars of mbufs used */
86                u_long  sb_mbmax;       /* max chars of mbufs to use */
87                long    sb_lowat;       /* low water mark */
88                struct  mbuf *sb_mb;    /* the mbuf chain */
89                struct  selinfo sb_sel; /* process selecting read/write */
90                short   sb_flags;       /* flags, see below */
91                u_long  sb_timeo;       /* timeout for read/write */
92                void    (*sb_wakeup) __P((struct socket *, caddr_t));
93                caddr_t sb_wakeuparg;   /* arg for above */
94        } so_rcv, so_snd;
95#define SB_MAX          (256*1024)      /* default for max chars in sockbuf */
96#define SB_LOCK         0x01            /* lock on data queue */
97#define SB_WANT         0x02            /* someone is waiting to lock */
98#define SB_WAIT         0x04            /* someone is waiting for data/space */
99#define SB_SEL          0x08            /* someone is selecting */
100#define SB_ASYNC        0x10            /* ASYNC I/O, need signals */
101#define SB_NOTIFY       (SB_WAIT|SB_SEL|SB_ASYNC)
102#define SB_NOINTR       0x40            /* operations not interruptible */
103
104        caddr_t so_tpcb;                /* Wisc. protocol control block XXX */
105        void    (*so_upcall) __P((struct socket *so, caddr_t arg, int waitf));
106        caddr_t so_upcallarg;           /* Arg for above */
107        uid_t   so_uid;                 /* who opened the socket */
108};
109
110/*
111 * Socket state bits.
112 */
113#define SS_NOFDREF              0x0001  /* no file table ref any more */
114#define SS_ISCONNECTED          0x0002  /* socket connected to a peer */
115#define SS_ISCONNECTING         0x0004  /* in process of connecting to peer */
116#define SS_ISDISCONNECTING      0x0008  /* in process of disconnecting */
117#define SS_CANTSENDMORE         0x0010  /* can't send more data to peer */
118#define SS_CANTRCVMORE          0x0020  /* can't receive more data from peer */
119#define SS_RCVATMARK            0x0040  /* at mark on input */
120
121#define SS_PRIV                 0x0080  /* privileged for broadcast, raw... */
122#define SS_NBIO                 0x0100  /* non-blocking ops */
123#define SS_ASYNC                0x0200  /* async i/o notify */
124#define SS_ISCONFIRMING         0x0400  /* deciding to accept connection req */
125
126#define SS_INCOMP               0x0800  /* unaccepted, incomplete connection */
127#define SS_COMP                 0x1000  /* unaccepted, complete connection */
128
129
130/*
131 * Macros for sockets and socket buffering.
132 */
133
134/*
135 * How much space is there in a socket buffer (so->so_snd or so->so_rcv)?
136 * This is problematical if the fields are unsigned, as the space might
137 * still be negative (cc > hiwat or mbcnt > mbmax).  Should detect
138 * overflow and return 0.  Should use "lmin" but it doesn't exist now.
139 */
140#define sbspace(sb) \
141    ((long) imin((int)((sb)->sb_hiwat - (sb)->sb_cc), \
142         (int)((sb)->sb_mbmax - (sb)->sb_mbcnt)))
143
144/* do we have to send all at once on a socket? */
145#define sosendallatonce(so) \
146    ((so)->so_proto->pr_flags & PR_ATOMIC)
147
148/* can we read something from so? */
149#define soreadable(so) \
150    ((so)->so_rcv.sb_cc >= (so)->so_rcv.sb_lowat || \
151        ((so)->so_state & SS_CANTRCVMORE) || \
152        (so)->so_comp.tqh_first || (so)->so_error)
153
154/* can we write something to so? */
155#define sowriteable(so) \
156    ((sbspace(&(so)->so_snd) >= (so)->so_snd.sb_lowat && \
157        (((so)->so_state&SS_ISCONNECTED) || \
158          ((so)->so_proto->pr_flags&PR_CONNREQUIRED)==0)) || \
159     ((so)->so_state & SS_CANTSENDMORE) || \
160     (so)->so_error)
161
162/* adjust counters in sb reflecting allocation of m */
163#define sballoc(sb, m) { \
164        (sb)->sb_cc += (m)->m_len; \
165        (sb)->sb_mbcnt += MSIZE; \
166        if ((m)->m_flags & M_EXT) \
167                (sb)->sb_mbcnt += (m)->m_ext.ext_size; \
168}
169
170/* adjust counters in sb reflecting freeing of m */
171#define sbfree(sb, m) { \
172        (sb)->sb_cc -= (m)->m_len; \
173        (sb)->sb_mbcnt -= MSIZE; \
174        if ((m)->m_flags & M_EXT) \
175                (sb)->sb_mbcnt -= (m)->m_ext.ext_size; \
176}
177
178/*
179 * Set lock on sockbuf sb; sleep if lock is already held.
180 * Unless SB_NOINTR is set on sockbuf, sleep is interruptible.
181 * Returns error without lock if sleep is interrupted.
182 */
183#define sblock(sb, wf) ((sb)->sb_flags & SB_LOCK ? \
184                (((wf) == M_WAITOK) ? sb_lock(sb) : EWOULDBLOCK) : \
185                ((sb)->sb_flags |= SB_LOCK), 0)
186
187/* release lock on sockbuf sb */
188#define sbunlock(sb) { \
189        (sb)->sb_flags &= ~SB_LOCK; \
190        if ((sb)->sb_flags & SB_WANT) { \
191                (sb)->sb_flags &= ~SB_WANT; \
192                wakeup((caddr_t)&(sb)->sb_flags); \
193        } \
194}
195
196#define sorwakeup(so)   { sowakeup((so), &(so)->so_rcv); \
197                          if ((so)->so_upcall) \
198                            (*((so)->so_upcall))((so), (so)->so_upcallarg, M_DONTWAIT); \
199                        }
200
201#define sowwakeup(so)   sowakeup((so), &(so)->so_snd)
202
203#ifdef KERNEL
204extern u_long   sb_max;
205
206/* to catch callers missing new second argument to sonewconn: */
207#define sonewconn(head, connstatus)     sonewconn1((head), (connstatus))
208
209struct filedesc;
210struct mbuf;
211struct sockaddr;
212struct stat;
213
214/*
215 * File operations on sockets.
216 */
217int     soo_ioctl __P((struct file *fp, int cmd, caddr_t data,
218            struct proc *p));
219int     soo_select __P((struct file *fp, int which, struct proc *p));
220int     soo_stat __P((struct socket *so, struct stat *ub));
221
222/*
223 * From uipc_socket and friends
224 */
225int     getsock __P((struct filedesc *fdp, int fdes, struct file **fpp));
226int     sockargs __P((struct mbuf **mp, caddr_t buf, int buflen, int type));
227void    sbappend __P((struct sockbuf *sb, struct mbuf *m));
228int     sbappendaddr __P((struct sockbuf *sb, struct sockaddr *asa,
229            struct mbuf *m0, struct mbuf *control));
230int     sbappendcontrol __P((struct sockbuf *sb, struct mbuf *m0,
231            struct mbuf *control));
232void    sbappendrecord __P((struct sockbuf *sb, struct mbuf *m0));
233void    sbcheck __P((struct sockbuf *sb));
234void    sbcompress __P((struct sockbuf *sb, struct mbuf *m, struct mbuf *n));
235struct mbuf *
236        sbcreatecontrol __P((caddr_t p, int size, int type, int level));
237void    sbdrop __P((struct sockbuf *sb, int len));
238void    sbdroprecord __P((struct sockbuf *sb));
239void    sbflush __P((struct sockbuf *sb));
240void    sbinsertoob __P((struct sockbuf *sb, struct mbuf *m0));
241void    sbrelease __P((struct sockbuf *sb));
242int     sbreserve __P((struct sockbuf *sb, u_long cc));
243int     sbwait __P((struct sockbuf *sb));
244int     sb_lock __P((struct sockbuf *sb));
245int     soabort __P((struct socket *so));
246int     soaccept __P((struct socket *so, struct mbuf *nam));
247int     sobind __P((struct socket *so, struct mbuf *nam));
248void    socantrcvmore __P((struct socket *so));
249void    socantsendmore __P((struct socket *so));
250int     soclose __P((struct socket *so));
251int     soconnect __P((struct socket *so, struct mbuf *nam));
252int     soconnect2 __P((struct socket *so1, struct socket *so2));
253int     socreate __P((int dom, struct socket **aso, int type, int proto,
254            struct proc *p));
255int     sodisconnect __P((struct socket *so));
256void    sofree __P((struct socket *so));
257int     sogetopt __P((struct socket *so, int level, int optname,
258            struct mbuf **mp));
259void    sohasoutofband __P((struct socket *so));
260void    soisconnected __P((struct socket *so));
261void    soisconnecting __P((struct socket *so));
262void    soisdisconnected __P((struct socket *so));
263void    soisdisconnecting __P((struct socket *so));
264int     solisten __P((struct socket *so, int backlog));
265struct socket *
266        sodropablereq __P((struct socket *head));
267struct socket *
268        sonewconn1 __P((struct socket *head, int connstatus));
269int     soreceive __P((struct socket *so, struct mbuf **paddr, struct uio *uio,
270            struct mbuf **mp0, struct mbuf **controlp, int *flagsp));
271int     soreserve __P((struct socket *so, u_long sndcc, u_long rcvcc));
272void    sorflush __P((struct socket *so));
273int     sosend __P((struct socket *so, struct mbuf *addr, struct uio *uio,
274            struct mbuf *top, struct mbuf *control, int flags));
275int     sosetopt __P((struct socket *so, int level, int optname,
276            struct mbuf *m0));
277int     soshutdown __P((struct socket *so, int how));
278void    sowakeup __P((struct socket *so, struct sockbuf *sb));
279#endif /* KERNEL */
280
281#endif /* !_SYS_SOCKETVAR_H_ */
Note: See TracBrowser for help on using the repository browser.