xref: /illumos-gate/usr/src/lib/libc/port/gen/event_port.c (revision 9525b14bcdeb5b5f6f95ab27c2f48f18bd2ec829)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "lint.h"
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <sys/port_impl.h>
35 #include <errno.h>
36 #include <stdlib.h>
37 #include <sys/systm.h>
38 #include <libc.h>
39 
40 /*
41  * The second argument of _portfs(PORT_CREATE, 0,,,) represents the version
42  * number of the event ports framework. The version number is required to
43  * identify possible changes/extensions of the port_event_t structure. If an
44  * extension is required the port_create() function will be mapped to a second
45  * library create function like port_create_v1(PORT_CREATE, VERSION,,,)
46  * VERSION will be a number > 0.
47  * As long as such an extension is not required the second argument will be
48  * set to 0 and no check will be done in the kernel interface.
49  */
50 int
51 port_create()
52 {
53 	rval_t	r;
54 	r.r_vals = _portfs(PORT_CREATE | PORT_SYS_NOPORT, 0, 0, 0, 0, 0);
55 	return (r.r_val1);
56 }
57 
58 int
59 port_associate(int port, int source, uintptr_t object, int events, void *user)
60 {
61 	rval_t	r;
62 	r.r_vals = _portfs(PORT_ASSOCIATE, port, source, object, events,
63 	    (uintptr_t)user);
64 	return (r.r_val1);
65 }
66 
67 
68 int
69 port_get(int port, port_event_t *pe, struct timespec *to)
70 {
71 	rval_t	r;
72 	if (to)
73 		r.r_vals = _portfs(PORT_GET, port, (uintptr_t)pe, to->tv_sec,
74 		    to->tv_nsec, (uintptr_t)to);
75 	else
76 		r.r_vals = _portfs(PORT_GET, port, (uintptr_t)pe, 0, 0, NULL);
77 	return (r.r_val1);
78 }
79 
80 int
81 port_getn(int port, port_event_t list[], uint_t max, uint_t *nget,
82     struct timespec *timeout)
83 {
84 	rval_t	r;
85 	if (nget == NULL) {
86 		errno = EINVAL;
87 		return (-1);
88 	}
89 	r.r_vals = _portfs(PORT_GETN, port, (uintptr_t)list, max, *nget,
90 	    (uintptr_t)timeout);
91 	if (r.r_val1 == -1) {
92 		/* global error, errno is already set */
93 		return (-1);
94 	}
95 	*nget = r.r_val1;
96 	if (r.r_val2 == ETIME) {
97 		errno = ETIME;
98 		return (-1);
99 	}
100 	return (r.r_val2);
101 }
102 
103 int
104 port_dissociate(int port, int source, uintptr_t object)
105 {
106 	rval_t	r;
107 	r.r_vals = _portfs(PORT_DISSOCIATE, port, source, object, 0, 0);
108 	return (r.r_val1);
109 }
110 
111 int
112 port_send(int port, int events, void *user)
113 {
114 	rval_t	r;
115 	r.r_vals = _portfs(PORT_SEND, port, events, (uintptr_t)user, NULL,
116 	    NULL);
117 	return (r.r_val1);
118 }
119 
120 /*
121  * _port_dispatch() will block if there are not resources available to
122  * satisfy the request.
123  */
124 
125 int
126 _port_dispatch(int port, int flags, int source, int events, uintptr_t object,
127     void *user)
128 {
129 	rval_t	r;
130 	if (flags & PORT_SHARE_EVENT)
131 		r.r_vals = _portfs(PORT_DISPATCH, port, source, events, object,
132 		    (uintptr_t)user);
133 	else
134 		r.r_vals = _portfs(PORT_DISPATCH | PORT_SYS_NOSHARE, port,
135 		    source, events, object, (uintptr_t)user);
136 	return (r.r_val1);
137 }
138 
139 int
140 port_sendn(int ports[], int errors[], uint_t nent, int events, void *user)
141 {
142 	rval_t	r;
143 	uint_t	offset;
144 	uint_t	lnent;
145 	uint_t	nevents;
146 	if (nent <= PORT_MAX_LIST) {
147 		r.r_vals = _portfs(PORT_SENDN | PORT_SYS_NOPORT,
148 		    (uintptr_t)ports, (uintptr_t)errors, nent, events,
149 		    (uintptr_t)user);
150 		return (r.r_val1);
151 	}
152 
153 	/* use chunks of max PORT_MAX_LIST elements per syscall */
154 	nevents = 0;
155 	for (offset = 0; offset < nent; ) {
156 		lnent = nent - offset;
157 		if (nent - offset > PORT_MAX_LIST)
158 			lnent = PORT_MAX_LIST;
159 		else
160 			lnent = nent - offset;
161 		r.r_vals = _portfs(PORT_SENDN | PORT_SYS_NOPORT,
162 		    (uintptr_t)&ports[offset], (uintptr_t)&errors[offset],
163 		    lnent, events, (uintptr_t)user);
164 		if (r.r_val2 == -1) {
165 			/* global error, return last no of events submitted */
166 			if (nevents)
167 				return (nevents);
168 			return (-1);
169 		}
170 		nevents += r.r_val1;
171 		offset += lnent;
172 	}
173 	/* list submitted */
174 	return (nevents);
175 }
176 
177 int
178 port_alert(int port, int flags, int events, void *user)
179 {
180 	rval_t	r;
181 	r.r_vals = _portfs(PORT_ALERT, port, flags, events, (uintptr_t)user,
182 	    NULL);
183 	return (r.r_val1);
184 }
185