Tizen 2.1 base
[platform/upstream/gcd.git] / kqueue-1.0.4 / src / solaris / kevent.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 <port.h>
19 #include <poll.h>
20
21 #include "sys/event.h"
22 #include "private.h"
23
24 const struct filter evfilt_vnode = EVFILT_NOTIMPL;
25 const struct filter evfilt_proc  = EVFILT_NOTIMPL;
26
27 /* Dump a poll(2) events bitmask */
28 static char *
29 poll_events_dump(short events)
30 {
31     static char __thread buf[512];
32
33 #define _PL_DUMP(attrib) \
34     if (events == attrib) \
35        strcat(&buf[0], " "#attrib);
36
37     snprintf(&buf[0], 512, "events = %hd 0x%o (", events, events);
38     _PL_DUMP(POLLIN);
39     _PL_DUMP(POLLPRI);
40     _PL_DUMP(POLLOUT);
41     _PL_DUMP(POLLRDNORM);
42     _PL_DUMP(POLLRDBAND);
43     _PL_DUMP(POLLWRBAND);
44     _PL_DUMP(POLLERR);
45     _PL_DUMP(POLLHUP);
46     _PL_DUMP(POLLNVAL);
47     strcat(&buf[0], ")");
48
49     return (&buf[0]);
50
51 #undef _PL_DUMP
52 }
53
54 static char *
55 port_event_dump(port_event_t *evt)
56 {
57     static char __thread buf[512];
58
59     if (evt == NULL)
60         return "(null)";
61
62 #define PE_DUMP(attrib) \
63     if (evt->portev_source == attrib) \
64        strcat(&buf[0], #attrib);
65
66     snprintf(&buf[0], 512,
67                 " { object = %u, user = %p, %s, source = %d (",
68                 (unsigned int) evt->portev_object,
69                 evt->portev_user,
70                 poll_events_dump(evt->portev_events),
71                 evt->portev_source);
72     PE_DUMP(PORT_SOURCE_AIO);
73     PE_DUMP(PORT_SOURCE_FD);
74     PE_DUMP(PORT_SOURCE_TIMER);
75     PE_DUMP(PORT_SOURCE_USER);
76     PE_DUMP(PORT_SOURCE_ALERT);
77     strcat(&buf[0], ") }\n");
78
79     return (&buf[0]);
80 #undef PE_DUMP
81 }
82
83 int
84 kevent_wait(struct kqueue *kq, const struct timespec *timeout)
85 {
86     port_event_t *pe = (port_event_t *) pthread_getspecific(kq->kq_port_event);
87
88     int rv;
89     uint_t nget = 1;
90
91     reset_errno();
92     dbg_printf("waiting for events (timeout=%p)", timeout);
93     rv = port_getn(kq->kq_port, pe, 1, &nget, (struct timespec *) timeout);
94     dbg_printf("rv=%d errno=%d (%s) nget=%d", 
95                 rv, errno, strerror(errno), nget);
96     if (rv < 0) {
97         if (errno == ETIME) {
98             dbg_puts("no events within the given timeout");
99             return (0);
100         }
101         if (errno == EINTR) {
102             dbg_puts("signal caught");
103             return (-1);
104         }
105         dbg_perror("port_get(2)");
106         return (-1);
107     }
108
109     return (nget);
110 }
111
112 int
113 kevent_copyout(struct kqueue *kq, int nready,
114         struct kevent *eventlist, int nevents)
115 {
116     port_event_t *pe = (port_event_t *) pthread_getspecific(kq->kq_port_event);
117     struct filter *filt;
118     int rv;
119
120     dbg_printf("%s", port_event_dump(pe));
121     switch (pe->portev_source) {
122         case PORT_SOURCE_FD:
123         filt = pe->portev_user;
124         rv = filt->kf_copyout(filt, eventlist, nevents);
125         break;
126
127         case PORT_SOURCE_TIMER:
128         filter_lookup(&filt, kq, EVFILT_TIMER);
129         rv = filt->kf_copyout(filt, eventlist, nevents);
130         break;
131
132         case PORT_SOURCE_USER:
133         switch (pe->portev_events) {
134             case X_PORT_SOURCE_SIGNAL:
135                 filter_lookup(&filt, kq, EVFILT_SIGNAL);
136                 rv = filt->kf_copyout(filt, eventlist, nevents);
137                 break;
138             case X_PORT_SOURCE_USER:
139                 filter_lookup(&filt, kq, EVFILT_USER);
140                 rv = filt->kf_copyout(filt, eventlist, nevents);
141                 break;
142             default:
143                 dbg_puts("unsupported portev_events");
144                 abort();
145         }
146         break;
147
148         default:
149                 dbg_puts("unsupported source");
150                 abort();
151     }
152     if (rv < 0) {
153         dbg_puts("kevent_copyout failed");
154         return (-1);
155     }
156
157     return (1);
158 }