summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/port_impl.h
blob: a80e7afc846731bd8ba2487b3d8c6e312223443f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_PORT_IMPL_H
#define	_SYS_PORT_IMPL_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Note:
 * The contents of this file are private to the implementation of the
 * Solaris system and event ports subsystem and are subject to change
 * at any time without notice.
 */

#include <sys/poll_impl.h>
#include <sys/port.h>
#include <sys/port_kernel.h>
#include <sys/vnode.h>

/*
 * port system call codes
 */
#define	PORT_CREATE	0	/* create a port */
#define	PORT_ASSOCIATE	1	/* register object or object list */
#define	PORT_DISSOCIATE	2	/* remove object association */
#define	PORT_SEND	3	/* send user-defined event to a port */
#define	PORT_SENDN	4	/* send user-defined event to a list of ports */
#define	PORT_GET	5	/* receive object with events */
#define	PORT_GETN	6	/* receive list of objects with events */
#define	PORT_ALERT	7	/* set port in alert mode */
#define	PORT_DISPATCH	8	/* dispatch object with events */

#define	PORT_SYS_NOPORT		0x100	/* system call without port-id */
#define	PORT_SYS_NOSHARE	0x200	/* non shareable event */
#define	PORT_CODE_MASK		0xff

/* port_dispatch() flags */
#define	PORT_SHARE_EVENT	0x01	/* event can be shared between procs */

/* port limits */
#define	PORT_MAX_LIST	8192	/* max. # of list ent. per syscall */

#ifdef _KERNEL

#define	PORT_SCACHE_SIZE	16	/* start source cache size */
#define	PORT_SHASH(cookie)	(cookie & (PORT_SCACHE_SIZE-1))

/* portkev_flags masks */
#define	PORT_CLEANUP_DONE	(PORT_KEV_FREE|PORT_KEV_DONEQ)
#define	PORT_KEV_CACHE		(PORT_KEV_CACHED|PORT_KEV_SCACHED)
#define	PORT_KEV_WIRED		(PORT_KEV_PRIVATE|PORT_KEV_CACHE)

#define	PORT_FREE_EVENT(pev)	(((pev)->portkev_flags & PORT_KEV_CACHE) == 0)

typedef struct port_alert {
	int	portal_events;		/* passed to alert event */
	pid_t	portal_pid;		/* owner of the alert mode */
	uintptr_t portal_object;	/* passed to alert event */
	void	*portal_user;		/* passed to alert event */
} port_alert_t;

/*
 * The port_queue_t structure is responsible for the management of all
 * event activities within a port.
 */
typedef struct port_queue {
	kmutex_t 	portq_mutex;
	kcondvar_t	portq_closecv;
	kcondvar_t	portq_block_cv;
	int		portq_flags;
	uint_t		portq_nent;	/* number of events in the queue */
	uint_t		portq_nget;	/* events required for waiting thread */
	uint_t		portq_tnent;	/* number of events in the temp queue */
	int		portq_thrcnt;	/* # of threads waiting for events */
	int		portq_getn;	/* # of threads retrieving events */
	struct	portget	*portq_thread;	/* queue of waiting threads */
	struct port_fdcache *portq_pcp;	/* fd cache */
	list_t		portq_list;	/* port event list */
	list_t		portq_get_list;	/* port event list for port_get(n) */
	kmutex_t	portq_source_mutex;
	port_source_t	**portq_scache;
	port_alert_t	portq_alert;	/* alert event data	*/
} port_queue_t;

/* defines for portq_flags */
#define	PORTQ_ALERT	   0x01	/* port in alert state */
#define	PORTQ_CLOSE	   0x02 /* closing port	*/
#define	PORTQ_WAIT_EVENTS  0x04 /* waiting for new events */
#define	PORTQ_POLLIN	   0x08 /* events available in the event queue */
#define	PORTQ_POLLOUT	   0x10 /* space available for new events */
#define	PORTQ_BLOCKED	   0x20 /* port is blocked by port_getn() */
#define	PORTQ_POLLWK_PEND  0x40 /* pollwakeup is pending, blocks port close */

#define	VTOEP(v)  ((struct port *)(v->v_data))
#define	EPTOV(ep) ((struct vnode *)(ep)->port_vnode)


typedef	struct	port {
	vnode_t		*port_vnode;
	kmutex_t	port_mutex;
	kcondvar_t	port_cv;	/* resource control */
	uint_t		port_flags;
	pid_t		port_pid;
	int		port_fd;
	uint_t		port_max_events; /* max. number of event per port */
	uint_t		port_max_list;	/* max. number of list structs	*/
	uint_t		port_curr;	/* current number of event structs */
	pollhead_t	port_pollhd;
	timespec_t	port_ctime;
	uid_t		port_uid;
	gid_t		port_gid;
	port_queue_t	port_queue;	/* global queue */
} port_t;

/* defines for port_flags */
#define	PORT_INIT	0x01		/* port initialized */
#define	PORT_CLOSED	0x02		/* owner closed the port */
#define	PORT_EVENTS	0x04		/* waiting for event resources */

/*
 * global control structure of port framework
 */
typedef	struct	port_control {
	kmutex_t	pc_mutex;
	uint_t		pc_nents;	/* ports currently allocated */
	struct	kmem_cache *pc_cache;	/* port event structures */
} port_control_t;


/*
 * Every thread waiting on an object will use this structure to store
 * all dependencies (flags, counters, events) before it awakes with
 * some events/transactions completed
 */
typedef	struct	portget {
	int		portget_state;
	uint_t		portget_nget;	/* number of expected events */
	pid_t		portget_pid;
	kcondvar_t	portget_cv;
	port_alert_t	portget_alert;
	struct	portget	*portget_next;
	struct	portget	*portget_prev;
} portget_t;

/* defines for portget_state */
#define	PORTGET_ALERT		0x01	/* wake up and return alert event */

extern	port_control_t	port_control;
extern	uint_t	port_max_list;

/*
 * port_getn() needs this structure to manage inter-process event delivery.
 */
typedef struct	port_gettimer {
	ushort_t	pgt_flags;
	ushort_t	pgt_loop;
	int		pgt_timecheck;
	timespec_t	pgt_rqtime;
	timespec_t	*pgt_rqtp;
	struct timespec	*pgt_timeout;
} port_gettimer_t;

/* pgt_flags */
#define	PORTGET_ONE		0x01	/* return only 1 object */
#define	PORTGET_WAIT_EVENTS	0x02	/* thread is waiting for new events */

/*
 * portfd_t is required to synchronize the association of fds with a port
 * and the per-process list of open files.
 * There is a pointer to a portfd structure in uf_entry_t.
 * If a fd is closed then closeandsetf() is able to detect the association of
 * the fd with a port or with a list of ports. closeandsetf() will dissociate
 * the fd from the port(s).
 */
typedef struct portfd {
	struct polldat	pfd_pd;
	struct portfd	*pfd_next;
	struct portfd	*pfd_prev;
} portfd_t;

#define	PFTOD(pfd)	(&(pfd)->pfd_pd)
#define	PDTOF(pdp)	((struct portfd *)(pdp))
#define	PORT_FD_BUCKET(pcp, fd) \
	(&(pcp)->pc_hash[((fd) % (pcp)->pc_hashsize)])

/*
 * port_kstat_t contains the event port kernel values which are
 * exported to kstat.
 * Currently only the number of active ports is exported.
 */
typedef struct port_kstat {
	kstat_named_t	pks_ports;
} port_kstat_t;

/* misc functions */
int	port_alloc_event_block(port_t *, int, int, struct port_kevent **);
void	port_push_eventq(port_queue_t *);
void	port_remove_done_event(struct port_kevent *);
struct	port_kevent *port_get_kevent(list_t *, struct port_kevent *);
void	port_block(port_queue_t *);
void	port_unblock(port_queue_t *);

/* PORT_SOURCE_FD cache management */
void port_pcache_remove_fd(port_fdcache_t *, portfd_t *);
int port_remove_fd_object(portfd_t *, struct port *, port_fdcache_t *);

/* file close management */
extern void addfd_port(int, portfd_t *);
extern void delfd_port(int, portfd_t *);

#endif	/* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_PORT_IMPL_H */