10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51885Sraf * Common Development and Distribution License (the "License"). 61885Sraf * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211885Sraf 220Sstevel@tonic-gate /* 23*4863Spraks * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #ifndef _SYS_PORT_IMPL_H 280Sstevel@tonic-gate #define _SYS_PORT_IMPL_H 290Sstevel@tonic-gate 300Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 310Sstevel@tonic-gate 320Sstevel@tonic-gate #ifdef __cplusplus 330Sstevel@tonic-gate extern "C" { 340Sstevel@tonic-gate #endif 350Sstevel@tonic-gate 360Sstevel@tonic-gate /* 370Sstevel@tonic-gate * Note: 380Sstevel@tonic-gate * The contents of this file are private to the implementation of the 390Sstevel@tonic-gate * Solaris system and event ports subsystem and are subject to change 400Sstevel@tonic-gate * at any time without notice. 410Sstevel@tonic-gate */ 420Sstevel@tonic-gate 430Sstevel@tonic-gate #include <sys/poll_impl.h> 440Sstevel@tonic-gate #include <sys/port.h> 450Sstevel@tonic-gate #include <sys/port_kernel.h> 460Sstevel@tonic-gate #include <sys/vnode.h> 47*4863Spraks #include <sys/fem.h> 480Sstevel@tonic-gate 490Sstevel@tonic-gate /* 500Sstevel@tonic-gate * port system call codes 510Sstevel@tonic-gate */ 520Sstevel@tonic-gate #define PORT_CREATE 0 /* create a port */ 530Sstevel@tonic-gate #define PORT_ASSOCIATE 1 /* register object or object list */ 540Sstevel@tonic-gate #define PORT_DISSOCIATE 2 /* remove object association */ 550Sstevel@tonic-gate #define PORT_SEND 3 /* send user-defined event to a port */ 560Sstevel@tonic-gate #define PORT_SENDN 4 /* send user-defined event to a list of ports */ 570Sstevel@tonic-gate #define PORT_GET 5 /* receive object with events */ 580Sstevel@tonic-gate #define PORT_GETN 6 /* receive list of objects with events */ 590Sstevel@tonic-gate #define PORT_ALERT 7 /* set port in alert mode */ 600Sstevel@tonic-gate #define PORT_DISPATCH 8 /* dispatch object with events */ 610Sstevel@tonic-gate 620Sstevel@tonic-gate #define PORT_SYS_NOPORT 0x100 /* system call without port-id */ 630Sstevel@tonic-gate #define PORT_SYS_NOSHARE 0x200 /* non shareable event */ 640Sstevel@tonic-gate #define PORT_CODE_MASK 0xff 650Sstevel@tonic-gate 660Sstevel@tonic-gate /* port_dispatch() flags */ 670Sstevel@tonic-gate #define PORT_SHARE_EVENT 0x01 /* event can be shared between procs */ 680Sstevel@tonic-gate 690Sstevel@tonic-gate /* port limits */ 700Sstevel@tonic-gate #define PORT_MAX_LIST 8192 /* max. # of list ent. per syscall */ 710Sstevel@tonic-gate 720Sstevel@tonic-gate #ifdef _KERNEL 730Sstevel@tonic-gate 740Sstevel@tonic-gate #define PORT_SCACHE_SIZE 16 /* start source cache size */ 750Sstevel@tonic-gate #define PORT_SHASH(cookie) (cookie & (PORT_SCACHE_SIZE-1)) 760Sstevel@tonic-gate 770Sstevel@tonic-gate /* portkev_flags masks */ 780Sstevel@tonic-gate #define PORT_CLEANUP_DONE (PORT_KEV_FREE|PORT_KEV_DONEQ) 790Sstevel@tonic-gate #define PORT_KEV_CACHE (PORT_KEV_CACHED|PORT_KEV_SCACHED) 800Sstevel@tonic-gate #define PORT_KEV_WIRED (PORT_KEV_PRIVATE|PORT_KEV_CACHE) 810Sstevel@tonic-gate 820Sstevel@tonic-gate #define PORT_FREE_EVENT(pev) (((pev)->portkev_flags & PORT_KEV_CACHE) == 0) 830Sstevel@tonic-gate 840Sstevel@tonic-gate typedef struct port_alert { 850Sstevel@tonic-gate int portal_events; /* passed to alert event */ 860Sstevel@tonic-gate pid_t portal_pid; /* owner of the alert mode */ 870Sstevel@tonic-gate uintptr_t portal_object; /* passed to alert event */ 880Sstevel@tonic-gate void *portal_user; /* passed to alert event */ 890Sstevel@tonic-gate } port_alert_t; 900Sstevel@tonic-gate 910Sstevel@tonic-gate /* 920Sstevel@tonic-gate * The port_queue_t structure is responsible for the management of all 930Sstevel@tonic-gate * event activities within a port. 940Sstevel@tonic-gate */ 950Sstevel@tonic-gate typedef struct port_queue { 960Sstevel@tonic-gate kmutex_t portq_mutex; 970Sstevel@tonic-gate kcondvar_t portq_closecv; 981885Sraf kcondvar_t portq_block_cv; 990Sstevel@tonic-gate int portq_flags; 1000Sstevel@tonic-gate uint_t portq_nent; /* number of events in the queue */ 1010Sstevel@tonic-gate uint_t portq_nget; /* events required for waiting thread */ 1020Sstevel@tonic-gate uint_t portq_tnent; /* number of events in the temp queue */ 1030Sstevel@tonic-gate int portq_thrcnt; /* # of threads waiting for events */ 1040Sstevel@tonic-gate int portq_getn; /* # of threads retrieving events */ 1050Sstevel@tonic-gate struct portget *portq_thread; /* queue of waiting threads */ 1060Sstevel@tonic-gate struct port_fdcache *portq_pcp; /* fd cache */ 1070Sstevel@tonic-gate list_t portq_list; /* port event list */ 1080Sstevel@tonic-gate list_t portq_get_list; /* port event list for port_get(n) */ 1090Sstevel@tonic-gate kmutex_t portq_source_mutex; 1100Sstevel@tonic-gate port_source_t **portq_scache; 1110Sstevel@tonic-gate port_alert_t portq_alert; /* alert event data */ 1120Sstevel@tonic-gate } port_queue_t; 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate /* defines for portq_flags */ 1150Sstevel@tonic-gate #define PORTQ_ALERT 0x01 /* port in alert state */ 1160Sstevel@tonic-gate #define PORTQ_CLOSE 0x02 /* closing port */ 1170Sstevel@tonic-gate #define PORTQ_WAIT_EVENTS 0x04 /* waiting for new events */ 1180Sstevel@tonic-gate #define PORTQ_POLLIN 0x08 /* events available in the event queue */ 1190Sstevel@tonic-gate #define PORTQ_POLLOUT 0x10 /* space available for new events */ 1201885Sraf #define PORTQ_BLOCKED 0x20 /* port is blocked by port_getn() */ 1212948Spraks #define PORTQ_POLLWK_PEND 0x40 /* pollwakeup is pending, blocks port close */ 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate #define VTOEP(v) ((struct port *)(v->v_data)) 1240Sstevel@tonic-gate #define EPTOV(ep) ((struct vnode *)(ep)->port_vnode) 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate typedef struct port { 1280Sstevel@tonic-gate vnode_t *port_vnode; 1290Sstevel@tonic-gate kmutex_t port_mutex; 1300Sstevel@tonic-gate kcondvar_t port_cv; /* resource control */ 1310Sstevel@tonic-gate uint_t port_flags; 1320Sstevel@tonic-gate pid_t port_pid; 1330Sstevel@tonic-gate int port_fd; 1340Sstevel@tonic-gate uint_t port_max_events; /* max. number of event per port */ 1350Sstevel@tonic-gate uint_t port_max_list; /* max. number of list structs */ 1360Sstevel@tonic-gate uint_t port_curr; /* current number of event structs */ 1370Sstevel@tonic-gate pollhead_t port_pollhd; 1380Sstevel@tonic-gate timespec_t port_ctime; 1390Sstevel@tonic-gate uid_t port_uid; 1400Sstevel@tonic-gate gid_t port_gid; 1410Sstevel@tonic-gate port_queue_t port_queue; /* global queue */ 1420Sstevel@tonic-gate } port_t; 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate /* defines for port_flags */ 1450Sstevel@tonic-gate #define PORT_INIT 0x01 /* port initialized */ 1460Sstevel@tonic-gate #define PORT_CLOSED 0x02 /* owner closed the port */ 1470Sstevel@tonic-gate #define PORT_EVENTS 0x04 /* waiting for event resources */ 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate /* 1500Sstevel@tonic-gate * global control structure of port framework 1510Sstevel@tonic-gate */ 1520Sstevel@tonic-gate typedef struct port_control { 1530Sstevel@tonic-gate kmutex_t pc_mutex; 1540Sstevel@tonic-gate uint_t pc_nents; /* ports currently allocated */ 1550Sstevel@tonic-gate struct kmem_cache *pc_cache; /* port event structures */ 1560Sstevel@tonic-gate } port_control_t; 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate /* 1600Sstevel@tonic-gate * Every thread waiting on an object will use this structure to store 1610Sstevel@tonic-gate * all dependencies (flags, counters, events) before it awakes with 1620Sstevel@tonic-gate * some events/transactions completed 1630Sstevel@tonic-gate */ 1640Sstevel@tonic-gate typedef struct portget { 1650Sstevel@tonic-gate int portget_state; 1660Sstevel@tonic-gate uint_t portget_nget; /* number of expected events */ 1670Sstevel@tonic-gate pid_t portget_pid; 1680Sstevel@tonic-gate kcondvar_t portget_cv; 1690Sstevel@tonic-gate port_alert_t portget_alert; 1700Sstevel@tonic-gate struct portget *portget_next; 1710Sstevel@tonic-gate struct portget *portget_prev; 1720Sstevel@tonic-gate } portget_t; 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate /* defines for portget_state */ 1750Sstevel@tonic-gate #define PORTGET_ALERT 0x01 /* wake up and return alert event */ 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate extern port_control_t port_control; 1780Sstevel@tonic-gate extern uint_t port_max_list; 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate /* 1810Sstevel@tonic-gate * port_getn() needs this structure to manage inter-process event delivery. 1820Sstevel@tonic-gate */ 1830Sstevel@tonic-gate typedef struct port_gettimer { 1840Sstevel@tonic-gate ushort_t pgt_flags; 1850Sstevel@tonic-gate ushort_t pgt_loop; 1864123Sdm120769 int pgt_timecheck; 1870Sstevel@tonic-gate timespec_t pgt_rqtime; 1880Sstevel@tonic-gate timespec_t *pgt_rqtp; 1890Sstevel@tonic-gate struct timespec *pgt_timeout; 1900Sstevel@tonic-gate } port_gettimer_t; 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate /* pgt_flags */ 1930Sstevel@tonic-gate #define PORTGET_ONE 0x01 /* return only 1 object */ 1940Sstevel@tonic-gate #define PORTGET_WAIT_EVENTS 0x02 /* thread is waiting for new events */ 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate /* 1970Sstevel@tonic-gate * portfd_t is required to synchronize the association of fds with a port 1980Sstevel@tonic-gate * and the per-process list of open files. 1990Sstevel@tonic-gate * There is a pointer to a portfd structure in uf_entry_t. 2000Sstevel@tonic-gate * If a fd is closed then closeandsetf() is able to detect the association of 2010Sstevel@tonic-gate * the fd with a port or with a list of ports. closeandsetf() will dissociate 2020Sstevel@tonic-gate * the fd from the port(s). 2030Sstevel@tonic-gate */ 2040Sstevel@tonic-gate typedef struct portfd { 2050Sstevel@tonic-gate struct polldat pfd_pd; 2060Sstevel@tonic-gate struct portfd *pfd_next; 2070Sstevel@tonic-gate struct portfd *pfd_prev; 2080Sstevel@tonic-gate } portfd_t; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate #define PFTOD(pfd) (&(pfd)->pfd_pd) 2110Sstevel@tonic-gate #define PDTOF(pdp) ((struct portfd *)(pdp)) 2120Sstevel@tonic-gate #define PORT_FD_BUCKET(pcp, fd) \ 2130Sstevel@tonic-gate (&(pcp)->pc_hash[((fd) % (pcp)->pc_hashsize)]) 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate /* 216*4863Spraks * PORT_SOURCE_FILE -- File Events Notification sources 217*4863Spraks */ 218*4863Spraks #define PORT_FOP_BUCKET(pcp, id) \ 219*4863Spraks (portfop_t **)(&(pcp)->pfc_hash[(((ulong_t)id >> 8) & \ 220*4863Spraks (PORTFOP_HASHSIZE - 1))]) 221*4863Spraks 222*4863Spraks /* 223*4863Spraks * This structure is used to register a file object to be watched. 224*4863Spraks * 225*4863Spraks * The pfop_flags are protected by the vnode's pvp_mutex lock. 226*4863Spraks * The pfop list (vnode's list) is protected by the pvp_mutex when it is on 227*4863Spraks * the vnode's list. 228*4863Spraks * 229*4863Spraks * All the rest of the fields are protected by the port's source cache lock 230*4863Spraks * pfcp_lock. 231*4863Spraks */ 232*4863Spraks typedef struct portfop { 233*4863Spraks int pfop_events; 234*4863Spraks int pfop_flags; /* above flags. */ 235*4863Spraks uintptr_t pfop_object; /* object address */ 236*4863Spraks vnode_t *pfop_vp; 237*4863Spraks vnode_t *pfop_dvp; 238*4863Spraks port_t *pfop_pp; 239*4863Spraks fem_t *pfop_fem; 240*4863Spraks list_node_t pfop_node; /* list of pfop's per vnode */ 241*4863Spraks struct portfop *pfop_hashnext; /* hash list */ 242*4863Spraks pid_t pfop_pid; /* owner of portfop */ 243*4863Spraks struct portfop_cache *pfop_pcache; 244*4863Spraks port_kevent_t *pfop_pev; /* event pointers */ 245*4863Spraks char *pfop_cname; /* file component name */ 246*4863Spraks int pfop_clen; 247*4863Spraks } portfop_t; 248*4863Spraks 249*4863Spraks /* 250*4863Spraks * pfop_flags 251*4863Spraks */ 252*4863Spraks #define PORT_FOP_ACTIVE 0x1 253*4863Spraks #define PORT_FOP_REMOVING 0x2 254*4863Spraks #define PORT_FOP_KEV_ONQ 0x4 255*4863Spraks 256*4863Spraks typedef struct portfop_vfs { 257*4863Spraks vfs_t *pvfs; 258*4863Spraks int pvfs_unmount; /* 1 if unmount in progress */ 259*4863Spraks list_t pvfs_pvplist; /* list of vnodes from */ 260*4863Spraks fsem_t *pvfs_fsemp; 261*4863Spraks struct portfop_vfs *pvfs_next; /* hash list */ 262*4863Spraks } portfop_vfs_t; 263*4863Spraks 264*4863Spraks typedef struct portfop_vfs_hash { 265*4863Spraks kmutex_t pvfshash_mutex; 266*4863Spraks struct portfop_vfs *pvfshash_pvfsp; 267*4863Spraks } portfop_vfs_hash_t; 268*4863Spraks 269*4863Spraks typedef struct portfop_vp { 270*4863Spraks vnode_t *pvp_vp; 271*4863Spraks kmutex_t pvp_mutex; 272*4863Spraks int pvp_cnt; /* number of watches */ 273*4863Spraks list_t pvp_pfoplist; 274*4863Spraks list_node_t pvp_pvfsnode; 275*4863Spraks struct portfop *pvp_lpfop; /* oldest pfop */ 276*4863Spraks fem_t *pvp_femp; 277*4863Spraks struct portfop_vfs *pvp_pvfsp; 278*4863Spraks } portfop_vp_t; 279*4863Spraks 280*4863Spraks #define PORTFOP_PVFSHASH_SZ 256 281*4863Spraks #define PORTFOP_PVFSHASH(vfsp) (((uintptr_t)(vfsp) >> 4) % PORTFOP_PVFSHASH_SZ) 282*4863Spraks 283*4863Spraks /* 284*4863Spraks * file operations flag. 285*4863Spraks */ 286*4863Spraks 287*4863Spraks /* 288*4863Spraks * PORT_SOURCE_FILE - vnode operations 289*4863Spraks */ 290*4863Spraks 291*4863Spraks #define FOP_FILE_OPEN 0x00000001 292*4863Spraks #define FOP_FILE_READ 0x00000002 293*4863Spraks #define FOP_FILE_WRITE 0x00000004 294*4863Spraks #define FOP_FILE_MAP 0x00000008 295*4863Spraks #define FOP_FILE_IOCTL 0x00000010 296*4863Spraks #define FOP_FILE_CREATE 0x00000020 297*4863Spraks #define FOP_FILE_MKDIR 0x00000040 298*4863Spraks #define FOP_FILE_SYMLINK 0x00000080 299*4863Spraks #define FOP_FILE_LINK 0x00000100 300*4863Spraks #define FOP_FILE_RENAME 0x00000200 301*4863Spraks #define FOP_FILE_REMOVE 0x00000400 302*4863Spraks #define FOP_FILE_RMDIR 0x00000800 303*4863Spraks #define FOP_FILE_READDIR 0x00001000 304*4863Spraks #define FOP_FILE_RENAMESRC 0x00002000 305*4863Spraks #define FOP_FILE_RENAMEDST 0x00004000 306*4863Spraks #define FOP_FILE_REMOVEFILE 0x00008000 307*4863Spraks #define FOP_FILE_REMOVEDIR 0x00010000 308*4863Spraks #define FOP_FILE_SETSECATTR 0x00020000 309*4863Spraks #define FOP_FILE_SETATTR_ATIME 0x00040000 310*4863Spraks #define FOP_FILE_SETATTR_MTIME 0x00080000 311*4863Spraks #define FOP_FILE_SETATTR_CTIME 0x00100000 312*4863Spraks #define FOP_FILE_LINK_SRC 0x00200000 313*4863Spraks 314*4863Spraks /* 315*4863Spraks * File modification event. 316*4863Spraks */ 317*4863Spraks #define FOP_MODIFIED_MASK (FOP_FILE_WRITE|FOP_FILE_CREATE \ 318*4863Spraks |FOP_FILE_REMOVE|FOP_FILE_LINK \ 319*4863Spraks |FOP_FILE_RENAMESRC|FOP_FILE_RENAMEDST \ 320*4863Spraks |FOP_FILE_MKDIR|FOP_FILE_RMDIR \ 321*4863Spraks |FOP_FILE_SYMLINK|FOP_FILE_SETATTR_MTIME) 322*4863Spraks 323*4863Spraks /* 324*4863Spraks * File access event 325*4863Spraks */ 326*4863Spraks #define FOP_ACCESS_MASK (FOP_FILE_READ|FOP_FILE_READDIR \ 327*4863Spraks |FOP_FILE_MAP|FOP_FILE_SETATTR_ATIME) 328*4863Spraks 329*4863Spraks /* 330*4863Spraks * File attrib event 331*4863Spraks */ 332*4863Spraks #define FOP_ATTRIB_MASK (FOP_FILE_WRITE|FOP_FILE_CREATE \ 333*4863Spraks |FOP_FILE_REMOVE|FOP_FILE_LINK \ 334*4863Spraks |FOP_FILE_RENAMESRC|FOP_FILE_RENAMEDST \ 335*4863Spraks |FOP_FILE_MKDIR|FOP_FILE_RMDIR \ 336*4863Spraks |FOP_FILE_SYMLINK|FOP_FILE_SETATTR_CTIME \ 337*4863Spraks |FOP_FILE_LINK_SRC|FOP_FILE_SETSECATTR) 338*4863Spraks 339*4863Spraks 340*4863Spraks /* 341*4863Spraks * valid watchable events 342*4863Spraks */ 343*4863Spraks #define FILE_EVENTS_MASK (FILE_ACCESS|FILE_MODIFIED|FILE_ATTRIB \ 344*4863Spraks |FILE_NOFOLLOW) 345*4863Spraks /* --- End file events --- */ 346*4863Spraks 347*4863Spraks /* 3480Sstevel@tonic-gate * port_kstat_t contains the event port kernel values which are 3490Sstevel@tonic-gate * exported to kstat. 3500Sstevel@tonic-gate * Currently only the number of active ports is exported. 3510Sstevel@tonic-gate */ 3520Sstevel@tonic-gate typedef struct port_kstat { 3530Sstevel@tonic-gate kstat_named_t pks_ports; 3540Sstevel@tonic-gate } port_kstat_t; 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate /* misc functions */ 3570Sstevel@tonic-gate int port_alloc_event_block(port_t *, int, int, struct port_kevent **); 3580Sstevel@tonic-gate void port_push_eventq(port_queue_t *); 359*4863Spraks int port_remove_done_event(struct port_kevent *); 3600Sstevel@tonic-gate struct port_kevent *port_get_kevent(list_t *, struct port_kevent *); 3611885Sraf void port_block(port_queue_t *); 3621885Sraf void port_unblock(port_queue_t *); 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate /* PORT_SOURCE_FD cache management */ 3650Sstevel@tonic-gate void port_pcache_remove_fd(port_fdcache_t *, portfd_t *); 3663734Spraks int port_remove_fd_object(portfd_t *, struct port *, port_fdcache_t *); 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate /* file close management */ 3690Sstevel@tonic-gate extern void addfd_port(int, portfd_t *); 3700Sstevel@tonic-gate extern void delfd_port(int, portfd_t *); 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate #endif /* _KERNEL */ 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate #ifdef __cplusplus 3750Sstevel@tonic-gate } 3760Sstevel@tonic-gate #endif 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate #endif /* _SYS_PORT_IMPL_H */ 379