Home | History | Annotate | Download | only in sys
      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 2009 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 
     31 #ifdef	__cplusplus
     32 extern "C" {
     33 #endif
     34 
     35 /*
     36  * Note:
     37  * The contents of this file are private to the implementation of the
     38  * Solaris system and event ports subsystem and are subject to change
     39  * at any time without notice.
     40  */
     41 
     42 #include <sys/poll_impl.h>
     43 #include <sys/port.h>
     44 #include <sys/port_kernel.h>
     45 #include <sys/vnode.h>
     46 #include <sys/fem.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 #define	PORTQ_POLLWK_PEND  0x40 /* pollwakeup is pending, blocks port close */
    121 
    122 #define	VTOEP(v)  ((struct port *)(v->v_data))
    123 #define	EPTOV(ep) ((struct vnode *)(ep)->port_vnode)
    124 
    125 
    126 typedef	struct	port {
    127 	vnode_t		*port_vnode;
    128 	kmutex_t	port_mutex;
    129 	kcondvar_t	port_cv;	/* resource control */
    130 	uint_t		port_flags;
    131 	pid_t		port_pid;
    132 	int		port_fd;
    133 	uint_t		port_max_events; /* max. number of event per port */
    134 	uint_t		port_max_list;	/* max. number of list structs	*/
    135 	uint_t		port_curr;	/* current number of event structs */
    136 	pollhead_t	port_pollhd;
    137 	timespec_t	port_ctime;
    138 	uid_t		port_uid;
    139 	gid_t		port_gid;
    140 	port_queue_t	port_queue;	/* global queue */
    141 } port_t;
    142 
    143 /* defines for port_flags */
    144 #define	PORT_INIT	0x01		/* port initialized */
    145 #define	PORT_CLOSED	0x02		/* owner closed the port */
    146 #define	PORT_EVENTS	0x04		/* waiting for event resources */
    147 
    148 /*
    149  * global control structure of port framework
    150  */
    151 typedef	struct	port_control {
    152 	kmutex_t	pc_mutex;
    153 	uint_t		pc_nents;	/* ports currently allocated */
    154 	struct	kmem_cache *pc_cache;	/* port event structures */
    155 } port_control_t;
    156 
    157 
    158 /*
    159  * Every thread waiting on an object will use this structure to store
    160  * all dependencies (flags, counters, events) before it awakes with
    161  * some events/transactions completed
    162  */
    163 typedef	struct	portget {
    164 	int		portget_state;
    165 	uint_t		portget_nget;	/* number of expected events */
    166 	pid_t		portget_pid;
    167 	kcondvar_t	portget_cv;
    168 	port_alert_t	portget_alert;
    169 	struct	portget	*portget_next;
    170 	struct	portget	*portget_prev;
    171 } portget_t;
    172 
    173 /* defines for portget_state */
    174 #define	PORTGET_ALERT		0x01	/* wake up and return alert event */
    175 
    176 extern	port_control_t	port_control;
    177 extern	uint_t	port_max_list;
    178 
    179 /*
    180  * port_getn() needs this structure to manage inter-process event delivery.
    181  */
    182 typedef struct	port_gettimer {
    183 	ushort_t	pgt_flags;
    184 	ushort_t	pgt_loop;
    185 	int		pgt_timecheck;
    186 	timespec_t	pgt_rqtime;
    187 	timespec_t	*pgt_rqtp;
    188 	struct timespec	*pgt_timeout;
    189 } port_gettimer_t;
    190 
    191 /* pgt_flags */
    192 #define	PORTGET_ONE		0x01	/* return only 1 object */
    193 #define	PORTGET_WAIT_EVENTS	0x02	/* thread is waiting for new events */
    194 
    195 /*
    196  * portfd_t is required to synchronize the association of fds with a port
    197  * and the per-process list of open files.
    198  * There is a pointer to a portfd structure in uf_entry_t.
    199  * If a fd is closed then closeandsetf() is able to detect the association of
    200  * the fd with a port or with a list of ports. closeandsetf() will dissociate
    201  * the fd from the port(s).
    202  */
    203 typedef struct portfd {
    204 	struct polldat	pfd_pd;
    205 	struct portfd	*pfd_next;
    206 	struct portfd	*pfd_prev;
    207 	kthread_t	*pfd_thread;
    208 } portfd_t;
    209 
    210 #define	PFTOD(pfd)	(&(pfd)->pfd_pd)
    211 #define	PDTOF(pdp)	((struct portfd *)(pdp))
    212 #define	PORT_FD_BUCKET(pcp, fd) \
    213 	(&(pcp)->pc_hash[((fd) % (pcp)->pc_hashsize)])
    214 
    215 /*
    216  * PORT_SOURCE_FILE -- File Events Notification sources
    217  */
    218 #define	PORT_FOP_BUCKET(pcp, id) \
    219 	(portfop_t **)(&(pcp)->pfc_hash[(((ulong_t)id >> 8) & \
    220 	    (PORTFOP_HASHSIZE - 1))])
    221 
    222 /*
    223  * This structure is used to register a file object to be watched.
    224  *
    225  * The pfop_flags are protected by the vnode's pvp_mutex lock.
    226  * The pfop list (vnode's list) is protected by the pvp_mutex when it is on
    227  * the vnode's list.
    228  *
    229  * All the rest of the fields are protected by the port's source cache lock
    230  * pfcp_lock.
    231  */
    232 typedef struct  portfop {
    233 	int		pfop_events;
    234 	int		pfop_flags;	/* above flags. */
    235 	uintptr_t	pfop_object;	/* object address */
    236 	vnode_t		*pfop_vp;
    237 	vnode_t		*pfop_dvp;
    238 	port_t		*pfop_pp;
    239 	fem_t		*pfop_fem;
    240 	list_node_t	pfop_node;	/* list of pfop's per vnode */
    241 	struct portfop	*pfop_hashnext;	/* hash list */
    242 	pid_t		pfop_pid;	/* owner of portfop */
    243 	struct portfop_cache *pfop_pcache;
    244 	port_kevent_t	*pfop_pev;	/* event pointers */
    245 	char		*pfop_cname;	/* file component name */
    246 	int		pfop_clen;
    247 	kthread_t	*pfop_callrid;	/* thread doing the associate */
    248 } portfop_t;
    249 
    250 /*
    251  * pfop_flags
    252  */
    253 #define		PORT_FOP_ACTIVE		0x1
    254 #define		PORT_FOP_REMOVING	0x2
    255 #define		PORT_FOP_KEV_ONQ	0x4
    256 
    257 typedef struct portfop_vfs {
    258 	vfs_t		*pvfs;
    259 	int		pvfs_unmount;	/* 1 if unmount in progress */
    260 	list_t		pvfs_pvplist;	/* list of vnodes from */
    261 	fsem_t		*pvfs_fsemp;
    262 	struct portfop_vfs *pvfs_next;	/* hash list */
    263 } portfop_vfs_t;
    264 
    265 typedef struct portfop_vfs_hash {
    266 	kmutex_t	pvfshash_mutex;
    267 	struct portfop_vfs *pvfshash_pvfsp;
    268 } portfop_vfs_hash_t;
    269 
    270 typedef struct portfop_vp {
    271 	vnode_t		*pvp_vp;
    272 	kmutex_t	pvp_mutex;
    273 	int		pvp_cnt;	/* number of watches */
    274 	list_t		pvp_pfoplist;
    275 	list_node_t	pvp_pvfsnode;
    276 	struct portfop *pvp_lpfop;	/* oldest pfop */
    277 	fem_t		*pvp_femp;
    278 	struct portfop_vfs *pvp_pvfsp;
    279 } portfop_vp_t;
    280 
    281 #define	PORTFOP_PVFSHASH_SZ	256
    282 #define	PORTFOP_PVFSHASH(vfsp)	(((uintptr_t)(vfsp) >> 4) % PORTFOP_PVFSHASH_SZ)
    283 
    284 /*
    285  * file operations flag.
    286  */
    287 
    288 /*
    289  * PORT_SOURCE_FILE - vnode operations
    290  */
    291 
    292 #define	FOP_FILE_OPEN		0x00000001
    293 #define	FOP_FILE_READ		0x00000002
    294 #define	FOP_FILE_WRITE		0x00000004
    295 #define	FOP_FILE_MAP		0x00000008
    296 #define	FOP_FILE_IOCTL		0x00000010
    297 #define	FOP_FILE_CREATE		0x00000020
    298 #define	FOP_FILE_MKDIR		0x00000040
    299 #define	FOP_FILE_SYMLINK	0x00000080
    300 #define	FOP_FILE_LINK		0x00000100
    301 #define	FOP_FILE_RENAME		0x00000200
    302 #define	FOP_FILE_REMOVE		0x00000400
    303 #define	FOP_FILE_RMDIR		0x00000800
    304 #define	FOP_FILE_READDIR	0x00001000
    305 #define	FOP_FILE_RENAMESRC	0x00002000
    306 #define	FOP_FILE_RENAMEDST	0x00004000
    307 #define	FOP_FILE_REMOVEFILE	0x00008000
    308 #define	FOP_FILE_REMOVEDIR	0x00010000
    309 #define	FOP_FILE_SETSECATTR	0x00020000
    310 #define	FOP_FILE_SETATTR_ATIME	0x00040000
    311 #define	FOP_FILE_SETATTR_MTIME	0x00080000
    312 #define	FOP_FILE_SETATTR_CTIME	0x00100000
    313 #define	FOP_FILE_LINK_SRC	0x00200000
    314 
    315 /*
    316  * File modification event.
    317  */
    318 #define	FOP_MODIFIED_MASK	(FOP_FILE_WRITE|FOP_FILE_CREATE \
    319 				|FOP_FILE_REMOVE|FOP_FILE_LINK \
    320 				|FOP_FILE_RENAMESRC|FOP_FILE_RENAMEDST \
    321 				|FOP_FILE_MKDIR|FOP_FILE_RMDIR \
    322 				|FOP_FILE_SYMLINK|FOP_FILE_SETATTR_MTIME)
    323 
    324 /*
    325  * File access event
    326  */
    327 #define	FOP_ACCESS_MASK		(FOP_FILE_READ|FOP_FILE_READDIR \
    328 				|FOP_FILE_MAP|FOP_FILE_SETATTR_ATIME)
    329 
    330 /*
    331  * File attrib event
    332  */
    333 #define	FOP_ATTRIB_MASK		(FOP_FILE_WRITE|FOP_FILE_CREATE \
    334 				|FOP_FILE_REMOVE|FOP_FILE_LINK \
    335 				|FOP_FILE_RENAMESRC|FOP_FILE_RENAMEDST \
    336 				|FOP_FILE_MKDIR|FOP_FILE_RMDIR \
    337 				|FOP_FILE_SYMLINK|FOP_FILE_SETATTR_CTIME \
    338 				|FOP_FILE_LINK_SRC|FOP_FILE_SETSECATTR)
    339 
    340 
    341 /*
    342  * valid watchable events
    343  */
    344 #define	FILE_EVENTS_MASK	(FILE_ACCESS|FILE_MODIFIED|FILE_ATTRIB \
    345 				|FILE_NOFOLLOW)
    346 /* --- End file events --- */
    347 
    348 /*
    349  * port_kstat_t contains the event port kernel values which are
    350  * exported to kstat.
    351  * Currently only the number of active ports is exported.
    352  */
    353 typedef struct port_kstat {
    354 	kstat_named_t	pks_ports;
    355 } port_kstat_t;
    356 
    357 /* misc functions */
    358 int	port_alloc_event_block(port_t *, int, int, struct port_kevent **);
    359 void	port_push_eventq(port_queue_t *);
    360 int	port_remove_done_event(struct port_kevent *);
    361 struct	port_kevent *port_get_kevent(list_t *, struct port_kevent *);
    362 void	port_block(port_queue_t *);
    363 void	port_unblock(port_queue_t *);
    364 
    365 /* PORT_SOURCE_FD cache management */
    366 void port_pcache_remove_fd(port_fdcache_t *, portfd_t *);
    367 int port_remove_fd_object(portfd_t *, struct port *, port_fdcache_t *);
    368 
    369 /* file close management */
    370 extern void addfd_port(int, portfd_t *);
    371 extern void delfd_port(int, portfd_t *);
    372 
    373 #endif	/* _KERNEL */
    374 
    375 #ifdef	__cplusplus
    376 }
    377 #endif
    378 
    379 #endif	/* _SYS_PORT_IMPL_H */
    380