xref: /illumos-gate/usr/src/lib/libc/port/gen/event_port.c (revision d362b749)
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 2006 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 #pragma weak port_create = _port_create
30 #pragma weak port_associate = _port_associate
31 #pragma weak port_dissociate = _port_dissociate
32 #pragma weak port_send = _port_send
33 #pragma weak port_sendn = _port_sendn
34 #pragma weak port_get = _port_get
35 #pragma weak port_getn = _port_getn
36 #pragma weak port_alert = _port_alert
37 
38 #include "lint.h"
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 #include <unistd.h>
43 #include <sys/port_impl.h>
44 #include <errno.h>
45 #include <stdlib.h>
46 #include <sys/systm.h>
47 #include <libc.h>
48 
49 /*
50  * The second argument of _portfs(PORT_CREATE, 0,,,) represents the version
51  * number of the event ports framework. The version number is required to
52  * identify possible changes/extensions of the port_event_t structure. If an
53  * extension is required the port_create() function will be mapped to a second
54  * library create function like port_create_v1(PORT_CREATE, VERSION,,,)
55  * VERSION will be a number > 0.
56  * As long as such an extension is not required the second argument will be
57  * set to 0 and no check will be done in the kernel interface.
58  */
59 int
60 _port_create()
61 {
62 	rval_t	r;
63 	r.r_vals = _portfs(PORT_CREATE | PORT_SYS_NOPORT, 0, 0, 0, 0, 0);
64 	return (r.r_val1);
65 }
66 
67 int
68 _port_associate(int port, int source, uintptr_t object, int events, void *user)
69 {
70 	rval_t	r;
71 	r.r_vals = _portfs(PORT_ASSOCIATE, port, source, object, events,
72 	    (uintptr_t)user);
73 	return (r.r_val1);
74 }
75 
76 
77 int
78 _port_get(int port, port_event_t *pe, struct timespec *to)
79 {
80 	rval_t	r;
81 	if (to)
82 		r.r_vals = _portfs(PORT_GET, port, (uintptr_t)pe, to->tv_sec,
83 		    to->tv_nsec, (uintptr_t)to);
84 	else
85 		r.r_vals = _portfs(PORT_GET, port, (uintptr_t)pe, 0, 0, NULL);
86 	return (r.r_val1);
87 }
88 
89 int
90 _port_getn(int port, port_event_t list[], uint_t max, uint_t *nget,
91     struct timespec *timeout)
92 {
93 	rval_t	r;
94 	if (nget == NULL) {
95 		errno = EINVAL;
96 		return (-1);
97 	}
98 	r.r_vals = _portfs(PORT_GETN, port, (uintptr_t)list, max, *nget,
99 	    (uintptr_t)timeout);
100 	if (r.r_val1 == -1) {
101 		/* global error, errno is already set */
102 		return (-1);
103 	}
104 	*nget = r.r_val1;
105 	if (r.r_val2 == ETIME) {
106 		errno = ETIME;
107 		return (-1);
108 	}
109 	return (r.r_val2);
110 }
111 
112 int
113 _port_dissociate(int port, int source, uintptr_t object)
114 {
115 	rval_t	r;
116 	r.r_vals = _portfs(PORT_DISSOCIATE, port, source, object, 0, 0);
117 	return (r.r_val1);
118 }
119 
120 int
121 _port_send(int port, int events, void *user)
122 {
123 	rval_t	r;
124 	r.r_vals = _portfs(PORT_SEND, port, events, (uintptr_t)user, NULL,
125 	    NULL);
126 	return (r.r_val1);
127 }
128 
129 /*
130  * _port_dispatch() will block if there are not resources available to
131  * satisfy the request.
132  */
133 
134 int
135 _port_dispatch(int port, int flags, int source, int events, uintptr_t object,
136     void *user)
137 {
138 	rval_t	r;
139 	if (flags & PORT_SHARE_EVENT)
140 		r.r_vals = _portfs(PORT_DISPATCH, port, source, events, object,
141 		    (uintptr_t)user);
142 	else
143 		r.r_vals = _portfs(PORT_DISPATCH | PORT_SYS_NOSHARE, port,
144 		    source, events, object, (uintptr_t)user);
145 	return (r.r_val1);
146 }
147 
148 int
149 _port_sendn(int ports[], int errors[], uint_t nent, int events, void *user)
150 {
151 	rval_t	r;
152 	uint_t	offset;
153 	uint_t	lnent;
154 	uint_t	nevents;
155 	if (nent <= PORT_MAX_LIST) {
156 		r.r_vals = _portfs(PORT_SENDN | PORT_SYS_NOPORT,
157 		    (uintptr_t)ports, (uintptr_t)errors, nent, events,
158 		    (uintptr_t)user);
159 		return (r.r_val1);
160 	}
161 
162 	/* use chunks of max PORT_MAX_LIST elements per syscall */
163 	nevents = 0;
164 	for (offset = 0; offset < nent; ) {
165 		lnent = nent - offset;
166 		if (nent - offset > PORT_MAX_LIST)
167 			lnent = PORT_MAX_LIST;
168 		else
169 			lnent = nent - offset;
170 		r.r_vals = _portfs(PORT_SENDN | PORT_SYS_NOPORT,
171 		    (uintptr_t)&ports[offset], (uintptr_t)&errors[offset],
172 		    lnent, events, (uintptr_t)user);
173 		if (r.r_val2 == -1) {
174 			/* global error, return last no of events submitted */
175 			if (nevents)
176 				return (nevents);
177 			return (-1);
178 		}
179 		nevents += r.r_val1;
180 		offset += lnent;
181 	}
182 	/* list submitted */
183 	return (nevents);
184 }
185 
186 int
187 _port_alert(int port, int flags, int events, void *user)
188 {
189 	rval_t	r;
190 	r.r_vals = _portfs(PORT_ALERT, port, flags, events, (uintptr_t)user,
191 	    NULL);
192 	return (r.r_val1);
193 }
194