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*8587SPramod.Batni@Sun.COM * Copyright 2009 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 310Sstevel@tonic-gate #ifdef __cplusplus 320Sstevel@tonic-gate extern "C" { 330Sstevel@tonic-gate #endif 340Sstevel@tonic-gate 350Sstevel@tonic-gate /* 360Sstevel@tonic-gate * Note: 370Sstevel@tonic-gate * The contents of this file are private to the implementation of the 380Sstevel@tonic-gate * Solaris system and event ports subsystem and are subject to change 390Sstevel@tonic-gate * at any time without notice. 400Sstevel@tonic-gate */ 410Sstevel@tonic-gate 420Sstevel@tonic-gate #include <sys/poll_impl.h> 430Sstevel@tonic-gate #include <sys/port.h> 440Sstevel@tonic-gate #include <sys/port_kernel.h> 450Sstevel@tonic-gate #include <sys/vnode.h> 464863Spraks #include <sys/fem.h> 470Sstevel@tonic-gate 480Sstevel@tonic-gate /* 490Sstevel@tonic-gate * port system call codes 500Sstevel@tonic-gate */ 510Sstevel@tonic-gate #define PORT_CREATE 0 /* create a port */ 520Sstevel@tonic-gate #define PORT_ASSOCIATE 1 /* register object or object list */ 530Sstevel@tonic-gate #define PORT_DISSOCIATE 2 /* remove object association */ 540Sstevel@tonic-gate #define PORT_SEND 3 /* send user-defined event to a port */ 550Sstevel@tonic-gate #define PORT_SENDN 4 /* send user-defined event to a list of ports */ 560Sstevel@tonic-gate #define PORT_GET 5 /* receive object with events */ 570Sstevel@tonic-gate #define PORT_GETN 6 /* receive list of objects with events */ 580Sstevel@tonic-gate #define PORT_ALERT 7 /* set port in alert mode */ 590Sstevel@tonic-gate #define PORT_DISPATCH 8 /* dispatch object with events */ 600Sstevel@tonic-gate 610Sstevel@tonic-gate #define PORT_SYS_NOPORT 0x100 /* system call without port-id */ 620Sstevel@tonic-gate #define PORT_SYS_NOSHARE 0x200 /* non shareable event */ 630Sstevel@tonic-gate #define PORT_CODE_MASK 0xff 640Sstevel@tonic-gate 650Sstevel@tonic-gate /* port_dispatch() flags */ 660Sstevel@tonic-gate #define PORT_SHARE_EVENT 0x01 /* event can be shared between procs */ 670Sstevel@tonic-gate 680Sstevel@tonic-gate /* port limits */ 690Sstevel@tonic-gate #define PORT_MAX_LIST 8192 /* max. # of list ent. per syscall */ 700Sstevel@tonic-gate 710Sstevel@tonic-gate #ifdef _KERNEL 720Sstevel@tonic-gate 730Sstevel@tonic-gate #define PORT_SCACHE_SIZE 16 /* start source cache size */ 740Sstevel@tonic-gate #define PORT_SHASH(cookie) (cookie & (PORT_SCACHE_SIZE-1)) 750Sstevel@tonic-gate 760Sstevel@tonic-gate /* portkev_flags masks */ 770Sstevel@tonic-gate #define PORT_CLEANUP_DONE (PORT_KEV_FREE|PORT_KEV_DONEQ) 780Sstevel@tonic-gate #define PORT_KEV_CACHE (PORT_KEV_CACHED|PORT_KEV_SCACHED) 790Sstevel@tonic-gate #define PORT_KEV_WIRED (PORT_KEV_PRIVATE|PORT_KEV_CACHE) 800Sstevel@tonic-gate 810Sstevel@tonic-gate #define PORT_FREE_EVENT(pev) (((pev)->portkev_flags & PORT_KEV_CACHE) == 0) 820Sstevel@tonic-gate 830Sstevel@tonic-gate typedef struct port_alert { 840Sstevel@tonic-gate int portal_events; /* passed to alert event */ 850Sstevel@tonic-gate pid_t portal_pid; /* owner of the alert mode */ 860Sstevel@tonic-gate uintptr_t portal_object; /* passed to alert event */ 870Sstevel@tonic-gate void *portal_user; /* passed to alert event */ 880Sstevel@tonic-gate } port_alert_t; 890Sstevel@tonic-gate 900Sstevel@tonic-gate /* 910Sstevel@tonic-gate * The port_queue_t structure is responsible for the management of all 920Sstevel@tonic-gate * event activities within a port. 930Sstevel@tonic-gate */ 940Sstevel@tonic-gate typedef struct port_queue { 950Sstevel@tonic-gate kmutex_t portq_mutex; 960Sstevel@tonic-gate kcondvar_t portq_closecv; 971885Sraf kcondvar_t portq_block_cv; 980Sstevel@tonic-gate int portq_flags; 990Sstevel@tonic-gate uint_t portq_nent; /* number of events in the queue */ 1000Sstevel@tonic-gate uint_t portq_nget; /* events required for waiting thread */ 1010Sstevel@tonic-gate uint_t portq_tnent; /* number of events in the temp queue */ 1020Sstevel@tonic-gate int portq_thrcnt; /* # of threads waiting for events */ 1030Sstevel@tonic-gate int portq_getn; /* # of threads retrieving events */ 1040Sstevel@tonic-gate struct portget *portq_thread; /* queue of waiting threads */ 1050Sstevel@tonic-gate struct port_fdcache *portq_pcp; /* fd cache */ 1060Sstevel@tonic-gate list_t portq_list; /* port event list */ 1070Sstevel@tonic-gate list_t portq_get_list; /* port event list for port_get(n) */ 1080Sstevel@tonic-gate kmutex_t portq_source_mutex; 1090Sstevel@tonic-gate port_source_t **portq_scache; 1100Sstevel@tonic-gate port_alert_t portq_alert; /* alert event data */ 1110Sstevel@tonic-gate } port_queue_t; 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate /* defines for portq_flags */ 1140Sstevel@tonic-gate #define PORTQ_ALERT 0x01 /* port in alert state */ 1150Sstevel@tonic-gate #define PORTQ_CLOSE 0x02 /* closing port */ 1160Sstevel@tonic-gate #define PORTQ_WAIT_EVENTS 0x04 /* waiting for new events */ 1170Sstevel@tonic-gate #define PORTQ_POLLIN 0x08 /* events available in the event queue */ 1180Sstevel@tonic-gate #define PORTQ_POLLOUT 0x10 /* space available for new events */ 1191885Sraf #define PORTQ_BLOCKED 0x20 /* port is blocked by port_getn() */ 1202948Spraks #define PORTQ_POLLWK_PEND 0x40 /* pollwakeup is pending, blocks port close */ 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate #define VTOEP(v) ((struct port *)(v->v_data)) 1230Sstevel@tonic-gate #define EPTOV(ep) ((struct vnode *)(ep)->port_vnode) 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate typedef struct port { 1270Sstevel@tonic-gate vnode_t *port_vnode; 1280Sstevel@tonic-gate kmutex_t port_mutex; 1290Sstevel@tonic-gate kcondvar_t port_cv; /* resource control */ 1300Sstevel@tonic-gate uint_t port_flags; 1310Sstevel@tonic-gate pid_t port_pid; 1320Sstevel@tonic-gate int port_fd; 1330Sstevel@tonic-gate uint_t port_max_events; /* max. number of event per port */ 1340Sstevel@tonic-gate uint_t port_max_list; /* max. number of list structs */ 1350Sstevel@tonic-gate uint_t port_curr; /* current number of event structs */ 1360Sstevel@tonic-gate pollhead_t port_pollhd; 1370Sstevel@tonic-gate timespec_t port_ctime; 1380Sstevel@tonic-gate uid_t port_uid; 1390Sstevel@tonic-gate gid_t port_gid; 1400Sstevel@tonic-gate port_queue_t port_queue; /* global queue */ 1410Sstevel@tonic-gate } port_t; 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate /* defines for port_flags */ 1440Sstevel@tonic-gate #define PORT_INIT 0x01 /* port initialized */ 1450Sstevel@tonic-gate #define PORT_CLOSED 0x02 /* owner closed the port */ 1460Sstevel@tonic-gate #define PORT_EVENTS 0x04 /* waiting for event resources */ 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate /* 1490Sstevel@tonic-gate * global control structure of port framework 1500Sstevel@tonic-gate */ 1510Sstevel@tonic-gate typedef struct port_control { 1520Sstevel@tonic-gate kmutex_t pc_mutex; 1530Sstevel@tonic-gate uint_t pc_nents; /* ports currently allocated */ 1540Sstevel@tonic-gate struct kmem_cache *pc_cache; /* port event structures */ 1550Sstevel@tonic-gate } port_control_t; 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate /* 1590Sstevel@tonic-gate * Every thread waiting on an object will use this structure to store 1600Sstevel@tonic-gate * all dependencies (flags, counters, events) before it awakes with 1610Sstevel@tonic-gate * some events/transactions completed 1620Sstevel@tonic-gate */ 1630Sstevel@tonic-gate typedef struct portget { 1640Sstevel@tonic-gate int portget_state; 1650Sstevel@tonic-gate uint_t portget_nget; /* number of expected events */ 1660Sstevel@tonic-gate pid_t portget_pid; 1670Sstevel@tonic-gate kcondvar_t portget_cv; 1680Sstevel@tonic-gate port_alert_t portget_alert; 1690Sstevel@tonic-gate struct portget *portget_next; 1700Sstevel@tonic-gate struct portget *portget_prev; 1710Sstevel@tonic-gate } portget_t; 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate /* defines for portget_state */ 1740Sstevel@tonic-gate #define PORTGET_ALERT 0x01 /* wake up and return alert event */ 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate extern port_control_t port_control; 1770Sstevel@tonic-gate extern uint_t port_max_list; 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate /* 1800Sstevel@tonic-gate * port_getn() needs this structure to manage inter-process event delivery. 1810Sstevel@tonic-gate */ 1820Sstevel@tonic-gate typedef struct port_gettimer { 1830Sstevel@tonic-gate ushort_t pgt_flags; 1840Sstevel@tonic-gate ushort_t pgt_loop; 1854123Sdm120769 int pgt_timecheck; 1860Sstevel@tonic-gate timespec_t pgt_rqtime; 1870Sstevel@tonic-gate timespec_t *pgt_rqtp; 1880Sstevel@tonic-gate struct timespec *pgt_timeout; 1890Sstevel@tonic-gate } port_gettimer_t; 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate /* pgt_flags */ 1920Sstevel@tonic-gate #define PORTGET_ONE 0x01 /* return only 1 object */ 1930Sstevel@tonic-gate #define PORTGET_WAIT_EVENTS 0x02 /* thread is waiting for new events */ 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate /* 1960Sstevel@tonic-gate * portfd_t is required to synchronize the association of fds with a port 1970Sstevel@tonic-gate * and the per-process list of open files. 1980Sstevel@tonic-gate * There is a pointer to a portfd structure in uf_entry_t. 1990Sstevel@tonic-gate * If a fd is closed then closeandsetf() is able to detect the association of 2000Sstevel@tonic-gate * the fd with a port or with a list of ports. closeandsetf() will dissociate 2010Sstevel@tonic-gate * the fd from the port(s). 2020Sstevel@tonic-gate */ 2030Sstevel@tonic-gate typedef struct portfd { 2040Sstevel@tonic-gate struct polldat pfd_pd; 2050Sstevel@tonic-gate struct portfd *pfd_next; 2060Sstevel@tonic-gate struct portfd *pfd_prev; 207*8587SPramod.Batni@Sun.COM kthread_t *pfd_thread; 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 /* 2164863Spraks * PORT_SOURCE_FILE -- File Events Notification sources 2174863Spraks */ 2184863Spraks #define PORT_FOP_BUCKET(pcp, id) \ 2194863Spraks (portfop_t **)(&(pcp)->pfc_hash[(((ulong_t)id >> 8) & \ 2204863Spraks (PORTFOP_HASHSIZE - 1))]) 2214863Spraks 2224863Spraks /* 2234863Spraks * This structure is used to register a file object to be watched. 2244863Spraks * 2254863Spraks * The pfop_flags are protected by the vnode's pvp_mutex lock. 2264863Spraks * The pfop list (vnode's list) is protected by the pvp_mutex when it is on 2274863Spraks * the vnode's list. 2284863Spraks * 2294863Spraks * All the rest of the fields are protected by the port's source cache lock 2304863Spraks * pfcp_lock. 2314863Spraks */ 2324863Spraks typedef struct portfop { 2334863Spraks int pfop_events; 2344863Spraks int pfop_flags; /* above flags. */ 2354863Spraks uintptr_t pfop_object; /* object address */ 2364863Spraks vnode_t *pfop_vp; 2374863Spraks vnode_t *pfop_dvp; 2384863Spraks port_t *pfop_pp; 2394863Spraks fem_t *pfop_fem; 2404863Spraks list_node_t pfop_node; /* list of pfop's per vnode */ 2414863Spraks struct portfop *pfop_hashnext; /* hash list */ 2424863Spraks pid_t pfop_pid; /* owner of portfop */ 2434863Spraks struct portfop_cache *pfop_pcache; 2444863Spraks port_kevent_t *pfop_pev; /* event pointers */ 2454863Spraks char *pfop_cname; /* file component name */ 2464863Spraks int pfop_clen; 2476005Spraks kthread_t *pfop_callrid; /* thread doing the associate */ 2484863Spraks } portfop_t; 2494863Spraks 2504863Spraks /* 2514863Spraks * pfop_flags 2524863Spraks */ 2534863Spraks #define PORT_FOP_ACTIVE 0x1 2544863Spraks #define PORT_FOP_REMOVING 0x2 2554863Spraks #define PORT_FOP_KEV_ONQ 0x4 2564863Spraks 2574863Spraks typedef struct portfop_vfs { 2584863Spraks vfs_t *pvfs; 2594863Spraks int pvfs_unmount; /* 1 if unmount in progress */ 2604863Spraks list_t pvfs_pvplist; /* list of vnodes from */ 2614863Spraks fsem_t *pvfs_fsemp; 2624863Spraks struct portfop_vfs *pvfs_next; /* hash list */ 2634863Spraks } portfop_vfs_t; 2644863Spraks 2654863Spraks typedef struct portfop_vfs_hash { 2664863Spraks kmutex_t pvfshash_mutex; 2674863Spraks struct portfop_vfs *pvfshash_pvfsp; 2684863Spraks } portfop_vfs_hash_t; 2694863Spraks 2704863Spraks typedef struct portfop_vp { 2714863Spraks vnode_t *pvp_vp; 2724863Spraks kmutex_t pvp_mutex; 2734863Spraks int pvp_cnt; /* number of watches */ 2744863Spraks list_t pvp_pfoplist; 2754863Spraks list_node_t pvp_pvfsnode; 2764863Spraks struct portfop *pvp_lpfop; /* oldest pfop */ 2774863Spraks fem_t *pvp_femp; 2784863Spraks struct portfop_vfs *pvp_pvfsp; 2794863Spraks } portfop_vp_t; 2804863Spraks 2814863Spraks #define PORTFOP_PVFSHASH_SZ 256 2824863Spraks #define PORTFOP_PVFSHASH(vfsp) (((uintptr_t)(vfsp) >> 4) % PORTFOP_PVFSHASH_SZ) 2834863Spraks 2844863Spraks /* 2854863Spraks * file operations flag. 2864863Spraks */ 2874863Spraks 2884863Spraks /* 2894863Spraks * PORT_SOURCE_FILE - vnode operations 2904863Spraks */ 2914863Spraks 2924863Spraks #define FOP_FILE_OPEN 0x00000001 2934863Spraks #define FOP_FILE_READ 0x00000002 2944863Spraks #define FOP_FILE_WRITE 0x00000004 2954863Spraks #define FOP_FILE_MAP 0x00000008 2964863Spraks #define FOP_FILE_IOCTL 0x00000010 2974863Spraks #define FOP_FILE_CREATE 0x00000020 2984863Spraks #define FOP_FILE_MKDIR 0x00000040 2994863Spraks #define FOP_FILE_SYMLINK 0x00000080 3004863Spraks #define FOP_FILE_LINK 0x00000100 3014863Spraks #define FOP_FILE_RENAME 0x00000200 3024863Spraks #define FOP_FILE_REMOVE 0x00000400 3034863Spraks #define FOP_FILE_RMDIR 0x00000800 3044863Spraks #define FOP_FILE_READDIR 0x00001000 3054863Spraks #define FOP_FILE_RENAMESRC 0x00002000 3064863Spraks #define FOP_FILE_RENAMEDST 0x00004000 3074863Spraks #define FOP_FILE_REMOVEFILE 0x00008000 3084863Spraks #define FOP_FILE_REMOVEDIR 0x00010000 3094863Spraks #define FOP_FILE_SETSECATTR 0x00020000 3104863Spraks #define FOP_FILE_SETATTR_ATIME 0x00040000 3114863Spraks #define FOP_FILE_SETATTR_MTIME 0x00080000 3124863Spraks #define FOP_FILE_SETATTR_CTIME 0x00100000 3134863Spraks #define FOP_FILE_LINK_SRC 0x00200000 3144863Spraks 3154863Spraks /* 3164863Spraks * File modification event. 3174863Spraks */ 3184863Spraks #define FOP_MODIFIED_MASK (FOP_FILE_WRITE|FOP_FILE_CREATE \ 3194863Spraks |FOP_FILE_REMOVE|FOP_FILE_LINK \ 3204863Spraks |FOP_FILE_RENAMESRC|FOP_FILE_RENAMEDST \ 3214863Spraks |FOP_FILE_MKDIR|FOP_FILE_RMDIR \ 3224863Spraks |FOP_FILE_SYMLINK|FOP_FILE_SETATTR_MTIME) 3234863Spraks 3244863Spraks /* 3254863Spraks * File access event 3264863Spraks */ 3274863Spraks #define FOP_ACCESS_MASK (FOP_FILE_READ|FOP_FILE_READDIR \ 3284863Spraks |FOP_FILE_MAP|FOP_FILE_SETATTR_ATIME) 3294863Spraks 3304863Spraks /* 3314863Spraks * File attrib event 3324863Spraks */ 3334863Spraks #define FOP_ATTRIB_MASK (FOP_FILE_WRITE|FOP_FILE_CREATE \ 3344863Spraks |FOP_FILE_REMOVE|FOP_FILE_LINK \ 3354863Spraks |FOP_FILE_RENAMESRC|FOP_FILE_RENAMEDST \ 3364863Spraks |FOP_FILE_MKDIR|FOP_FILE_RMDIR \ 3374863Spraks |FOP_FILE_SYMLINK|FOP_FILE_SETATTR_CTIME \ 3384863Spraks |FOP_FILE_LINK_SRC|FOP_FILE_SETSECATTR) 3394863Spraks 3404863Spraks 3414863Spraks /* 3424863Spraks * valid watchable events 3434863Spraks */ 3444863Spraks #define FILE_EVENTS_MASK (FILE_ACCESS|FILE_MODIFIED|FILE_ATTRIB \ 3454863Spraks |FILE_NOFOLLOW) 3464863Spraks /* --- End file events --- */ 3474863Spraks 3484863Spraks /* 3490Sstevel@tonic-gate * port_kstat_t contains the event port kernel values which are 3500Sstevel@tonic-gate * exported to kstat. 3510Sstevel@tonic-gate * Currently only the number of active ports is exported. 3520Sstevel@tonic-gate */ 3530Sstevel@tonic-gate typedef struct port_kstat { 3540Sstevel@tonic-gate kstat_named_t pks_ports; 3550Sstevel@tonic-gate } port_kstat_t; 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate /* misc functions */ 3580Sstevel@tonic-gate int port_alloc_event_block(port_t *, int, int, struct port_kevent **); 3590Sstevel@tonic-gate void port_push_eventq(port_queue_t *); 3604863Spraks int port_remove_done_event(struct port_kevent *); 3610Sstevel@tonic-gate struct port_kevent *port_get_kevent(list_t *, struct port_kevent *); 3621885Sraf void port_block(port_queue_t *); 3631885Sraf void port_unblock(port_queue_t *); 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate /* PORT_SOURCE_FD cache management */ 3660Sstevel@tonic-gate void port_pcache_remove_fd(port_fdcache_t *, portfd_t *); 3673734Spraks int port_remove_fd_object(portfd_t *, struct port *, port_fdcache_t *); 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate /* file close management */ 3700Sstevel@tonic-gate extern void addfd_port(int, portfd_t *); 3710Sstevel@tonic-gate extern void delfd_port(int, portfd_t *); 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate #endif /* _KERNEL */ 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate #ifdef __cplusplus 3760Sstevel@tonic-gate } 3770Sstevel@tonic-gate #endif 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate #endif /* _SYS_PORT_IMPL_H */ 380