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