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 #ifndef _SYS_PORT_IMPL_H 28 #define _SYS_PORT_IMPL_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 /* 37 * Note: 38 * The contents of this file are private to the implementation of the 39 * Solaris system and event ports subsystem and are subject to change 40 * at any time without notice. 41 */ 42 43 #include <sys/poll_impl.h> 44 #include <sys/port.h> 45 #include <sys/port_kernel.h> 46 #include <sys/vnode.h> 47 48 /* 49 * port system call codes 50 */ 51 #define PORT_CREATE 0 /* create a port */ 52 #define PORT_ASSOCIATE 1 /* register object or object list */ 53 #define PORT_DISSOCIATE 2 /* remove object association */ 54 #define PORT_SEND 3 /* send user-defined event to a port */ 55 #define PORT_SENDN 4 /* send user-defined event to a list of ports */ 56 #define PORT_GET 5 /* receive object with events */ 57 #define PORT_GETN 6 /* receive list of objects with events */ 58 #define PORT_ALERT 7 /* set port in alert mode */ 59 #define PORT_DISPATCH 8 /* dispatch object with events */ 60 61 #define PORT_SYS_NOPORT 0x100 /* system call without port-id */ 62 #define PORT_SYS_NOSHARE 0x200 /* non shareable event */ 63 #define PORT_CODE_MASK 0xff 64 65 /* port_dispatch() flags */ 66 #define PORT_SHARE_EVENT 0x01 /* event can be shared between procs */ 67 68 /* port limits */ 69 #define PORT_MAX_LIST 8192 /* max. # of list ent. per syscall */ 70 71 #ifdef _KERNEL 72 73 #define PORT_SCACHE_SIZE 16 /* start source cache size */ 74 #define PORT_SHASH(cookie) (cookie & (PORT_SCACHE_SIZE-1)) 75 76 /* portkev_flags masks */ 77 #define PORT_CLEANUP_DONE (PORT_KEV_FREE|PORT_KEV_DONEQ) 78 #define PORT_KEV_CACHE (PORT_KEV_CACHED|PORT_KEV_SCACHED) 79 #define PORT_KEV_WIRED (PORT_KEV_PRIVATE|PORT_KEV_CACHE) 80 81 #define PORT_FREE_EVENT(pev) (((pev)->portkev_flags & PORT_KEV_CACHE) == 0) 82 83 typedef struct port_alert { 84 int portal_events; /* passed to alert event */ 85 pid_t portal_pid; /* owner of the alert mode */ 86 uintptr_t portal_object; /* passed to alert event */ 87 void *portal_user; /* passed to alert event */ 88 } port_alert_t; 89 90 /* 91 * The port_queue_t structure is responsible for the management of all 92 * event activities within a port. 93 */ 94 typedef struct port_queue { 95 kmutex_t portq_mutex; 96 kcondvar_t portq_closecv; 97 kcondvar_t portq_block_cv; 98 int portq_flags; 99 uint_t portq_nent; /* number of events in the queue */ 100 uint_t portq_nget; /* events required for waiting thread */ 101 uint_t portq_tnent; /* number of events in the temp queue */ 102 int portq_thrcnt; /* # of threads waiting for events */ 103 int portq_getn; /* # of threads retrieving events */ 104 struct portget *portq_thread; /* queue of waiting threads */ 105 struct port_fdcache *portq_pcp; /* fd cache */ 106 list_t portq_list; /* port event list */ 107 list_t portq_get_list; /* port event list for port_get(n) */ 108 kmutex_t portq_source_mutex; 109 port_source_t **portq_scache; 110 port_alert_t portq_alert; /* alert event data */ 111 } port_queue_t; 112 113 /* defines for portq_flags */ 114 #define PORTQ_ALERT 0x01 /* port in alert state */ 115 #define PORTQ_CLOSE 0x02 /* closing port */ 116 #define PORTQ_WAIT_EVENTS 0x04 /* waiting for new events */ 117 #define PORTQ_POLLIN 0x08 /* events available in the event queue */ 118 #define PORTQ_POLLOUT 0x10 /* space available for new events */ 119 #define PORTQ_BLOCKED 0x20 /* port is blocked by port_getn() */ 120 121 #define VTOEP(v) ((struct port *)(v->v_data)) 122 #define EPTOV(ep) ((struct vnode *)(ep)->port_vnode) 123 124 125 typedef struct port { 126 vnode_t *port_vnode; 127 kmutex_t port_mutex; 128 kcondvar_t port_cv; /* resource control */ 129 uint_t port_flags; 130 pid_t port_pid; 131 int port_fd; 132 uint_t port_max_events; /* max. number of event per port */ 133 uint_t port_max_list; /* max. number of list structs */ 134 uint_t port_curr; /* current number of event structs */ 135 pollhead_t port_pollhd; 136 timespec_t port_ctime; 137 uid_t port_uid; 138 gid_t port_gid; 139 port_queue_t port_queue; /* global queue */ 140 } port_t; 141 142 /* defines for port_flags */ 143 #define PORT_INIT 0x01 /* port initialized */ 144 #define PORT_CLOSED 0x02 /* owner closed the port */ 145 #define PORT_EVENTS 0x04 /* waiting for event resources */ 146 147 /* 148 * global control structure of port framework 149 */ 150 typedef struct port_control { 151 kmutex_t pc_mutex; 152 uint_t pc_nents; /* ports currently allocated */ 153 struct kmem_cache *pc_cache; /* port event structures */ 154 } port_control_t; 155 156 157 /* 158 * Every thread waiting on an object will use this structure to store 159 * all dependencies (flags, counters, events) before it awakes with 160 * some events/transactions completed 161 */ 162 typedef struct portget { 163 int portget_state; 164 uint_t portget_nget; /* number of expected events */ 165 pid_t portget_pid; 166 kcondvar_t portget_cv; 167 port_alert_t portget_alert; 168 struct portget *portget_next; 169 struct portget *portget_prev; 170 } portget_t; 171 172 /* defines for portget_state */ 173 #define PORTGET_ALERT 0x01 /* wake up and return alert event */ 174 175 extern port_control_t port_control; 176 extern uint_t port_max_list; 177 178 /* 179 * port_getn() needs this structure to manage inter-process event delivery. 180 */ 181 typedef struct port_gettimer { 182 ushort_t pgt_flags; 183 ushort_t pgt_loop; 184 int pgt_timecheck; 185 timespec_t pgt_rqtime; 186 timespec_t *pgt_rqtp; 187 struct timespec *pgt_timeout; 188 } port_gettimer_t; 189 190 /* pgt_flags */ 191 #define PORTGET_ONE 0x01 /* return only 1 object */ 192 #define PORTGET_WAIT_EVENTS 0x02 /* thread is waiting for new events */ 193 194 /* 195 * portfd_t is required to synchronize the association of fds with a port 196 * and the per-process list of open files. 197 * There is a pointer to a portfd structure in uf_entry_t. 198 * If a fd is closed then closeandsetf() is able to detect the association of 199 * the fd with a port or with a list of ports. closeandsetf() will dissociate 200 * the fd from the port(s). 201 */ 202 typedef struct portfd { 203 struct polldat pfd_pd; 204 struct portfd *pfd_next; 205 struct portfd *pfd_prev; 206 } portfd_t; 207 208 #define PFTOD(pfd) (&(pfd)->pfd_pd) 209 #define PDTOF(pdp) ((struct portfd *)(pdp)) 210 #define PORT_FD_BUCKET(pcp, fd) \ 211 (&(pcp)->pc_hash[((fd) % (pcp)->pc_hashsize)]) 212 213 /* 214 * port_kstat_t contains the event port kernel values which are 215 * exported to kstat. 216 * Currently only the number of active ports is exported. 217 */ 218 typedef struct port_kstat { 219 kstat_named_t pks_ports; 220 } port_kstat_t; 221 222 /* misc functions */ 223 int port_alloc_event_block(port_t *, int, int, struct port_kevent **); 224 void port_push_eventq(port_queue_t *); 225 void port_remove_done_event(struct port_kevent *); 226 struct port_kevent *port_get_kevent(list_t *, struct port_kevent *); 227 void port_block(port_queue_t *); 228 void port_unblock(port_queue_t *); 229 230 /* PORT_SOURCE_FD cache management */ 231 void port_pcache_remove_fd(port_fdcache_t *, portfd_t *); 232 void port_remove_fd_object(portfd_t *, struct port *, port_fdcache_t *); 233 234 /* file close management */ 235 extern void addfd_port(int, portfd_t *); 236 extern void delfd_port(int, portfd_t *); 237 238 #endif /* _KERNEL */ 239 240 #ifdef __cplusplus 241 } 242 #endif 243 244 #endif /* _SYS_PORT_IMPL_H */ 245