Home | History | Annotate | Download | only in gen
      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