Tizen 2.1 base
[platform/upstream/gcd.git] / kqueue-1.0.4 / src / common / knote.c
1 /*
2  * Copyright (c) 2009 Mark Heily <mark@heily.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/queue.h>
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include "private.h"
25
26 static int
27 knote_cmp(struct knote *a, struct knote *b)
28 {
29     return memcmp(&a->kev.ident, &b->kev.ident, sizeof(a->kev.ident)); 
30 }
31
32 RB_GENERATE(knt, knote, kntree_ent, knote_cmp)
33
34 struct knote *
35 knote_new(void)
36 {
37     struct knote *dst;
38
39     if ((dst = calloc(1, sizeof(*dst))) == NULL) 
40         return (NULL);
41
42     return (dst);
43 }
44
45 void
46 knote_insert(struct filter *filt, struct knote *kn)
47 {
48     RB_INSERT(knt, &filt->kf_knote, kn);
49 }
50
51 void
52 knote_free(struct filter *filt, struct knote *kn)
53 {
54     dbg_printf("filter=%s, ident=%u",
55             filter_name(kn->kev.filter), (unsigned int) kn->kev.ident);
56         RB_REMOVE(knt, &filt->kf_knote, kn);
57     if (kn->event_ent.tqe_prev) //XXX-FIXME what if this is the 1st entry??
58         TAILQ_REMOVE(&filt->kf_event, kn, event_ent);
59     filt->kn_delete(filt, kn);
60         free(kn);
61 }
62
63 void
64 knote_free_all(struct filter *filt)
65 {
66     struct knote *n1, *n2;
67
68     /* Destroy all pending events */
69     for (n1 = TAILQ_FIRST(&filt->kf_event); n1 != NULL; n1 = n2) {
70         n2 = TAILQ_NEXT(n1, event_ent);
71         free(n1);
72     }
73
74     /* Distroy all knotes */
75     for (n1 = RB_MIN(knt, &filt->kf_knote); n1 != NULL; n1 = n2) {
76         n2 = RB_NEXT(knt, filt->kf_knote, n1);
77         RB_REMOVE(knt, &filt->kf_knote, n1);
78         free(n1);
79     }
80 }
81
82 /* TODO: rename to knote_lookup_ident */
83 struct knote *
84 knote_lookup(struct filter *filt, short ident)
85 {
86     struct knote query;
87     struct knote *ent = NULL;
88
89     query.kev.ident = ident;
90     ent = RB_FIND(knt, &filt->kf_knote, &query);
91
92     dbg_printf("id=%d ent=%p", ident, ent);
93
94     return (ent);
95 }
96     
97 struct knote *
98 knote_lookup_data(struct filter *filt, intptr_t data)
99 {
100     struct knote *kn;
101
102     RB_FOREACH(kn, knt, &filt->kf_knote) {
103         if (data == kn->kev.data) 
104             break;
105     }
106     return (kn);
107 }
108
109 void
110 knote_enqueue(struct filter *filt, struct knote *kn)
111 {
112     /* XXX-FIXME: check if the knote is already on the eventlist */
113     TAILQ_INSERT_TAIL(&filt->kf_event, kn, event_ent);
114 }
115
116 struct knote *
117 knote_dequeue(struct filter *filt)
118 {
119     struct knote *kn;
120
121     if (TAILQ_EMPTY(&filt->kf_event)) {
122         kn = NULL;
123         dbg_puts("no events are pending");
124     } else {
125         kn = TAILQ_FIRST(&filt->kf_event);
126         TAILQ_REMOVE(&filt->kf_event, kn, event_ent);
127         memset(&kn->event_ent, 0, sizeof(kn->event_ent));
128     }
129
130     return (kn);
131 }
132
133 int
134 knote_events_pending(struct filter *filt)
135 {
136     int res;
137
138     res = TAILQ_EMPTY(&filt->kf_event);
139
140     return (res);
141 }
142
143 /*
144  * Test if a socket is active or passive.
145  */
146 int
147 knote_get_socket_type(struct knote *kn)
148 {
149     socklen_t slen;
150     int i, lsock;
151
152     slen = sizeof(lsock);
153     lsock = 0;
154     i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, &lsock, &slen);
155     if (i < 0) {
156         switch (errno) {
157             case ENOTSOCK:   /* same as lsock = 0 */
158                 return (0);
159                 break;
160             default:
161                 dbg_printf("getsockopt(3) failed: %s", strerror(errno));
162                 return (-1);
163         }
164     } else {
165         if (lsock) 
166             kn->flags |= KNFL_PASSIVE_SOCKET;
167         return (0);
168     }
169 }