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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * This file containts all the functions required for interactions of
31 * event sources with the event port file system.
34 #include <sys/types.h>
37 #include <sys/errno.h>
39 #include <sys/debug.h>
41 #include <sys/sysmacros.h>
42 #include <sys/systm.h>
43 #include <sys/bitmap.h>
45 #include <sys/atomic.h>
46 #include <sys/poll_impl.h>
47 #include <sys/port_impl.h>
50 * Maximum number of elements allowed to be passed in a single call of a
51 * port function (port_sendn(), port_getn(). We need to allocate kernel memory
52 * for all of them at once, so we can't let it scale without limit.
54 uint_t port_max_list
= PORT_MAX_LIST
;
55 port_control_t port_control
; /* Event port framework main structure */
58 * Block other threads from using a port.
59 * We enter holding portq->portq_mutex but
60 * we may drop and reacquire this lock.
61 * Callers must deal with this fact.
64 port_block(port_queue_t
*portq
)
66 ASSERT(MUTEX_HELD(&portq
->portq_mutex
));
68 while (portq
->portq_flags
& PORTQ_BLOCKED
)
69 cv_wait(&portq
->portq_block_cv
, &portq
->portq_mutex
);
70 portq
->portq_flags
|= PORTQ_BLOCKED
;
74 * Undo port_block(portq).
77 port_unblock(port_queue_t
*portq
)
79 ASSERT(MUTEX_HELD(&portq
->portq_mutex
));
81 portq
->portq_flags
&= ~PORTQ_BLOCKED
;
82 cv_signal(&portq
->portq_block_cv
);
86 * Called from pollwakeup(PORT_SOURCE_FD source) to determine
87 * if the port's fd needs to be notified of poll events. If yes,
88 * we mark the port indicating that pollwakeup() is referring
89 * it so that the port_t does not disappear. pollwakeup()
90 * calls port_pollwkdone() after notifying. In port_pollwkdone(),
91 * we clear the hold on the port_t (clear PORTQ_POLLWK_PEND).
94 port_pollwkup(port_t
*pp
)
98 portq
= &pp
->port_queue
;
99 mutex_enter(&portq
->portq_mutex
);
102 * Normally, we should not have a situation where PORTQ_POLLIN
103 * and PORTQ_POLLWK_PEND are set at the same time, but it is
104 * possible. So, in pollwakeup() we ensure that no new fd's get
105 * added to the pollhead between the time it notifies poll events
106 * and calls poll_wkupdone() where we clear the PORTQ_POLLWK_PEND flag.
108 if (portq
->portq_flags
& PORTQ_POLLIN
&&
109 !(portq
->portq_flags
& PORTQ_POLLWK_PEND
)) {
110 portq
->portq_flags
&= ~PORTQ_POLLIN
;
111 portq
->portq_flags
|= PORTQ_POLLWK_PEND
;
114 mutex_exit(&portq
->portq_mutex
);
119 port_pollwkdone(port_t
*pp
)
122 portq
= &pp
->port_queue
;
123 ASSERT(portq
->portq_flags
& PORTQ_POLLWK_PEND
);
124 mutex_enter(&portq
->portq_mutex
);
125 portq
->portq_flags
&= ~PORTQ_POLLWK_PEND
;
126 cv_signal(&pp
->port_cv
);
127 mutex_exit(&portq
->portq_mutex
);
132 * The port_send_event() function is used by all event sources to submit
133 * trigerred events to a port. All the data required for the event management
134 * is already stored in the port_kevent_t structure.
135 * The event port internal data is stored in the port_kevent_t structure
136 * during the allocation time (see port_alloc_event()). The data related to
137 * the event itself and to the event source management is stored in the
138 * port_kevent_t structure between the allocation time and submit time
139 * (see port_init_event()).
141 * This function is often called from interrupt level.
144 port_send_event(port_kevent_t
*pkevp
)
148 portq
= &pkevp
->portkev_port
->port_queue
;
149 mutex_enter(&portq
->portq_mutex
);
151 if (pkevp
->portkev_flags
& PORT_KEV_DONEQ
) {
152 /* Event already in the port queue */
153 if (pkevp
->portkev_source
== PORT_SOURCE_FD
) {
154 mutex_exit(&pkevp
->portkev_lock
);
156 mutex_exit(&portq
->portq_mutex
);
160 /* put event in the port queue */
161 list_insert_tail(&portq
->portq_list
, pkevp
);
165 * Remove the PORTQ_WAIT_EVENTS flag to indicate
166 * that new events are available.
168 portq
->portq_flags
&= ~PORTQ_WAIT_EVENTS
;
169 pkevp
->portkev_flags
|= PORT_KEV_DONEQ
; /* event enqueued */
171 if (pkevp
->portkev_source
== PORT_SOURCE_FD
) {
172 mutex_exit(&pkevp
->portkev_lock
);
175 /* Check if thread is in port_close() waiting for outstanding events */
176 if (portq
->portq_flags
& PORTQ_CLOSE
) {
177 /* Check if all outstanding events are already in port queue */
178 if (pkevp
->portkev_port
->port_curr
<= portq
->portq_nent
)
179 cv_signal(&portq
->portq_closecv
);
182 if (portq
->portq_getn
== 0) {
184 * No thread retrieving events -> check if enough events are
185 * available to satify waiting threads.
187 if (portq
->portq_thread
&&
188 (portq
->portq_nent
>= portq
->portq_nget
))
189 cv_signal(&portq
->portq_thread
->portget_cv
);
193 * If some thread is polling the port's fd, then notify it.
194 * For PORT_SOURCE_FD source, we don't need to call pollwakeup()
195 * here as it will result in a recursive call(PORT_SOURCE_FD source
196 * is pollwakeup()). Therefore pollwakeup() itself will notify the
197 * ports if being polled.
199 if (pkevp
->portkev_source
!= PORT_SOURCE_FD
&&
200 portq
->portq_flags
& PORTQ_POLLIN
) {
203 portq
->portq_flags
&= ~PORTQ_POLLIN
;
205 * Need to save port_t for calling pollwakeup since port_getn()
206 * may end up freeing pkevp once portq_mutex is dropped.
208 pp
= pkevp
->portkev_port
;
209 mutex_exit(&portq
->portq_mutex
);
210 pollwakeup(&pp
->port_pollhd
, POLLIN
);
212 mutex_exit(&portq
->portq_mutex
);
217 * The port_alloc_event() function has to be used by all event sources
218 * to request an slot for event notification.
219 * The slot reservation could be denied because of lack of resources.
220 * For that reason the event source should allocate an event slot as early
221 * as possible and be prepared to get an error code instead of the
222 * port event pointer.
223 * Al current event sources allocate an event slot during a system call
224 * entry. They return an error code to the application if an event slot
225 * could not be reserved.
226 * It is also recommended to associate the event source with the port
227 * before some other port function is used.
228 * The port argument is a file descriptor obtained by the application as
229 * a return value of port_create().
230 * Possible values of flags are:
232 * This is the standard type of port events. port_get(n) will free this
233 * type of event structures as soon as the events are delivered to the
236 * This type of event will be use for private use of the event source.
237 * The port_get(n) function will deliver events of such an structure to
238 * the application but it will not free the event structure itself.
239 * The event source must free this structure using port_free_event().
241 * This type of events is used when the event source helds an own
243 * The port_get(n) function will deliver events of such an structure to
244 * the application but it will not free the event structure itself.
245 * The event source must free this structure using port_free_event().
248 port_alloc_event(int port
, int flags
, int source
, port_kevent_t
**pkevpp
)
252 port_kevent_t
*pkevp
;
254 if ((fp
= getf(port
)) == NULL
)
257 if (fp
->f_vnode
->v_type
!= VPORT
) {
262 pkevp
= kmem_cache_alloc(port_control
.pc_cache
, KM_NOSLEEP
);
269 * port_max_events is controlled by the resource control
270 * process.port-max-events
272 pp
= VTOEP(fp
->f_vnode
);
273 mutex_enter(&pp
->port_queue
.portq_mutex
);
274 if (pp
->port_curr
>= pp
->port_max_events
) {
275 mutex_exit(&pp
->port_queue
.portq_mutex
);
276 kmem_cache_free(port_control
.pc_cache
, pkevp
);
281 mutex_exit(&pp
->port_queue
.portq_mutex
);
283 bzero(pkevp
, sizeof (port_kevent_t
));
284 mutex_init(&pkevp
->portkev_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
285 pkevp
->portkev_source
= source
;
286 pkevp
->portkev_flags
= flags
;
287 pkevp
->portkev_pid
= curproc
->p_pid
;
288 pkevp
->portkev_port
= pp
;
295 * This function is faster than the standard port_alloc_event() and
296 * can be used when the event source already allocated an event from
300 port_dup_event(port_kevent_t
*pkevp
, port_kevent_t
**pkevdupp
, int flags
)
304 error
= port_alloc_event_local(pkevp
->portkev_port
,
305 pkevp
->portkev_source
, flags
, pkevdupp
);
307 (*pkevdupp
)->portkev_pid
= pkevp
->portkev_pid
;
312 * port_alloc_event_local() is reserved for internal use only.
313 * It is doing the same job as port_alloc_event() but with the event port
314 * pointer as the first argument.
315 * The check of the validity of the port file descriptor is skipped here.
318 port_alloc_event_local(port_t
*pp
, int source
, int flags
,
319 port_kevent_t
**pkevpp
)
321 port_kevent_t
*pkevp
;
323 pkevp
= kmem_cache_alloc(port_control
.pc_cache
, KM_NOSLEEP
);
327 mutex_enter(&pp
->port_queue
.portq_mutex
);
328 if (pp
->port_curr
>= pp
->port_max_events
) {
329 mutex_exit(&pp
->port_queue
.portq_mutex
);
330 kmem_cache_free(port_control
.pc_cache
, pkevp
);
334 mutex_exit(&pp
->port_queue
.portq_mutex
);
336 bzero(pkevp
, sizeof (port_kevent_t
));
337 mutex_init(&pkevp
->portkev_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
338 pkevp
->portkev_flags
= flags
;
339 pkevp
->portkev_port
= pp
;
340 pkevp
->portkev_source
= source
;
341 pkevp
->portkev_pid
= curproc
->p_pid
;
347 * port_alloc_event_block() has the same functionality of port_alloc_event() +
348 * - it blocks if not enough event slots are available and
349 * - it blocks if not enough memory is available.
350 * Currently port_dispatch() is using this function to increase the
351 * reliability of event delivery for library event sources.
354 port_alloc_event_block(port_t
*pp
, int source
, int flags
,
355 port_kevent_t
**pkevpp
)
357 port_kevent_t
*pkevp
=
358 kmem_cache_alloc(port_control
.pc_cache
, KM_SLEEP
);
360 mutex_enter(&pp
->port_queue
.portq_mutex
);
361 while (pp
->port_curr
>= pp
->port_max_events
) {
362 if (!cv_wait_sig(&pp
->port_cv
, &pp
->port_queue
.portq_mutex
)) {
363 /* signal detected */
364 mutex_exit(&pp
->port_queue
.portq_mutex
);
365 kmem_cache_free(port_control
.pc_cache
, pkevp
);
370 mutex_exit(&pp
->port_queue
.portq_mutex
);
372 bzero(pkevp
, sizeof (port_kevent_t
));
373 mutex_init(&pkevp
->portkev_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
374 pkevp
->portkev_flags
= flags
;
375 pkevp
->portkev_port
= pp
;
376 pkevp
->portkev_source
= source
;
377 pkevp
->portkev_pid
= curproc
->p_pid
;
383 * Take an event out of the port queue
386 port_remove_event_doneq(port_kevent_t
*pkevp
, port_queue_t
*portq
)
388 ASSERT(MUTEX_HELD(&portq
->portq_mutex
));
389 list_remove(&portq
->portq_list
, pkevp
);
391 pkevp
->portkev_flags
&= ~PORT_KEV_DONEQ
;
395 * The port_remove_done_event() function takes a fired event out of the
397 * Currently this function is required to cancel a fired event because
398 * the application is delivering new association data (see port_associate_fd()).
401 port_remove_done_event(port_kevent_t
*pkevp
)
406 portq
= &pkevp
->portkev_port
->port_queue
;
407 mutex_enter(&portq
->portq_mutex
);
408 /* wait for port_get() or port_getn() */
410 if (pkevp
->portkev_flags
& PORT_KEV_DONEQ
) {
411 /* event still in port queue */
412 if (portq
->portq_getn
) {
414 * There could be still fired events in the temp queue;
415 * push those events back to the port queue and
416 * remove requested event afterwards.
418 port_push_eventq(portq
);
420 /* now remove event from the port queue */
421 port_remove_event_doneq(pkevp
, portq
);
425 mutex_exit(&portq
->portq_mutex
);
430 * Return port event back to the kmem_cache.
431 * If the event is currently in the port queue the event itself will only
432 * be set as invalid. The port_get(n) function will not deliver such events
433 * to the application and it will return them back to the kmem_cache.
436 port_free_event(port_kevent_t
*pkevp
)
441 pp
= pkevp
->portkev_port
;
444 if (pkevp
->portkev_flags
& PORT_ALLOC_PRIVATE
) {
445 port_free_event_local(pkevp
, 0);
449 portq
= &pp
->port_queue
;
450 mutex_enter(&portq
->portq_mutex
);
452 if (pkevp
->portkev_flags
& PORT_KEV_DONEQ
) {
453 pkevp
->portkev_flags
|= PORT_KEV_FREE
;
454 pkevp
->portkev_callback
= NULL
;
456 mutex_exit(&portq
->portq_mutex
);
461 if (pkevp
->portkev_flags
& PORT_KEV_CACHED
) {
462 mutex_exit(&portq
->portq_mutex
);
466 if (--pp
->port_curr
< pp
->port_max_events
)
467 cv_signal(&pp
->port_cv
);
468 if (portq
->portq_flags
& PORTQ_CLOSE
) {
470 * Another thread is closing the event port.
471 * That thread will sleep until all allocated event
472 * structures returned to the event port framework.
473 * The portq_mutex is used to synchronize the status
474 * of the allocated event structures (port_curr).
476 if (pp
->port_curr
<= portq
->portq_nent
)
477 cv_signal(&portq
->portq_closecv
);
479 mutex_exit(&portq
->portq_mutex
);
480 port_free_event_local(pkevp
, 1);
484 * This event port internal function is used by port_free_event() and
485 * other port internal functions to return event structures back to the
489 port_free_event_local(port_kevent_t
*pkevp
, int counter
)
491 port_t
*pp
= pkevp
->portkev_port
;
492 port_queue_t
*portq
= &pp
->port_queue
;
495 pkevp
->portkev_callback
= NULL
;
496 pkevp
->portkev_flags
= 0;
497 pkevp
->portkev_port
= NULL
;
498 mutex_destroy(&pkevp
->portkev_lock
);
499 kmem_cache_free(port_control
.pc_cache
, pkevp
);
501 mutex_enter(&portq
->portq_mutex
);
503 if (--pp
->port_curr
< pp
->port_max_events
)
504 cv_signal(&pp
->port_cv
);
506 wakeup
= (portq
->portq_flags
& PORTQ_POLLOUT
);
507 portq
->portq_flags
&= ~PORTQ_POLLOUT
;
508 mutex_exit(&portq
->portq_mutex
);
510 /* Submit a POLLOUT event if requested */
512 pollwakeup(&pp
->port_pollhd
, POLLOUT
);
516 * port_init_event(port_event_t *pev, uintptr_t object, void *user,
517 * int (*port_callback)(void *, int *, pid_t, int, void *), void *sysarg);
518 * This function initializes most of the "wired" elements of the port
519 * event structure. This is normally being used just after the allocation
520 * of the port event structure.
521 * pkevp : pointer to the port event structure
522 * object : object associated with this event structure
523 * user : user defined pointer delivered with the association function
525 * Address of the callback function which will be called
526 * - just before the event is delivered to the application.
527 * The callback function is called in user context and can be
528 * used for copyouts, e.g.
529 * - on close() or dissociation of the event. The sub-system
530 * must remove immediately every existing association of
531 * some object with this event.
532 * sysarg : event source propietary data
535 port_init_event(port_kevent_t
*pkevp
, uintptr_t object
, void *user
,
536 int (*port_callback
)(void *, int *, pid_t
, int, void *),
539 pkevp
->portkev_object
= object
;
540 pkevp
->portkev_user
= user
;
541 pkevp
->portkev_callback
= port_callback
;
542 pkevp
->portkev_arg
= sysarg
;
546 * This routine removes a portfd_t from the fd cache's hash table.
549 port_pcache_remove_fd(port_fdcache_t
*pcp
, portfd_t
*pfd
)
554 polldat_t
*pdp
= PFTOD(pfd
);
556 ASSERT(MUTEX_HELD(&pcp
->pc_lock
));
557 bucket
= PORT_FD_BUCKET(pcp
, pdp
->pd_fd
);
558 cpdp
= PFTOD(*bucket
);
560 *bucket
= PDTOF(pdp
->pd_hashnext
);
561 if (--pcp
->pc_fdcount
== 0) {
563 * signal the thread which may have blocked in
564 * port_close_sourcefd() on lastclose waiting
565 * for pc_fdcount to drop to 0.
567 cv_signal(&pcp
->pc_lclosecv
);
569 kmem_free(pfd
, sizeof (portfd_t
));
573 while (cpdp
!= NULL
) {
575 cpdp
= cpdp
->pd_hashnext
;
577 /* polldat struct found */
578 lpdp
->pd_hashnext
= pdp
->pd_hashnext
;
579 if (--pcp
->pc_fdcount
== 0) {
581 * signal the thread which may have blocked in
582 * port_close_sourcefd() on lastclose waiting
583 * for pc_fdcount to drop to 0.
585 cv_signal(&pcp
->pc_lclosecv
);
590 ASSERT(cpdp
!= NULL
);
591 kmem_free(pfd
, sizeof (portfd_t
));
595 * The port_push_eventq() function is used to move all remaining events
596 * from the temporary queue used in port_get(n)() to the standard port
600 port_push_eventq(port_queue_t
*portq
)
603 * Append temporary portq_get_list to the port queue. On return
604 * the temporary portq_get_list is empty.
606 list_move_tail(&portq
->portq_list
, &portq
->portq_get_list
);
607 portq
->portq_nent
+= portq
->portq_tnent
;
608 portq
->portq_tnent
= 0;
612 * The port_remove_fd_object() function frees all resources associated with
613 * delivered portfd_t structure. Returns 1 if the port_kevent was found
614 * and removed from the port queue.
617 port_remove_fd_object(portfd_t
*pfd
, port_t
*pp
, port_fdcache_t
*pcp
)
620 polldat_t
*pdp
= PFTOD(pfd
);
621 port_kevent_t
*pkevp
;
625 ASSERT(MUTEX_HELD(&pcp
->pc_lock
));
626 if (pdp
->pd_php
!= NULL
) {
627 pollhead_delete(pdp
->pd_php
, pdp
);
630 pkevp
= pdp
->pd_portev
;
631 portq
= &pp
->port_queue
;
632 mutex_enter(&portq
->portq_mutex
);
634 if (pkevp
->portkev_flags
& PORT_KEV_DONEQ
) {
635 if (portq
->portq_getn
&& portq
->portq_tnent
) {
637 * move events from the temporary "get" queue
638 * back to the port queue
640 port_push_eventq(portq
);
642 /* cleanup merged port queue */
643 port_remove_event_doneq(pkevp
, portq
);
647 mutex_exit(&portq
->portq_mutex
);
648 if (pkevp
->portkev_callback
) {
649 (void) (*pkevp
->portkev_callback
)(pkevp
->portkev_arg
,
650 &error
, pkevp
->portkev_pid
, PORT_CALLBACK_DISSOCIATE
,
653 port_free_event_local(pkevp
, 0);
655 /* remove polldat struct */
656 port_pcache_remove_fd(pcp
, pfd
);
661 * The port_close_fd() function dissociates a file descriptor from a port
662 * and removes all allocated resources.
663 * close(2) detects in the uf_entry_t structure that the fd is associated
664 * with a port (at least one port).
665 * The fd can be associated with several ports.
668 port_close_pfd(portfd_t
*pfd
)
674 * the portfd_t passed in should be for this proc.
676 ASSERT(curproc
->p_pid
== PFTOD(pfd
)->pd_portev
->portkev_pid
);
677 pp
= PFTOD(pfd
)->pd_portev
->portkev_port
;
678 pcp
= pp
->port_queue
.portq_pcp
;
679 mutex_enter(&pcp
->pc_lock
);
680 (void) port_remove_fd_object(pfd
, pp
, pcp
);
681 mutex_exit(&pcp
->pc_lock
);
685 * The port_associate_ksource() function associates an event source with a port.
686 * On port_close() all associated sources are requested to free all local
687 * resources associated with the event port.
688 * The association of a source with a port can only be done one time. Further
689 * calls of this function will only increment the reference counter.
690 * The allocated port_source_t structure is removed from the port as soon as
691 * the reference counter becomes 0.
695 port_associate_ksource(int port
, int source
, port_source_t
**portsrc
,
696 void (*port_src_close
)(void *, int, pid_t
, int), void *arg
,
697 int (*port_src_associate
)(port_kevent_t
*, int, int, uintptr_t, void *))
704 if ((fp
= getf(port
)) == NULL
)
707 if (fp
->f_vnode
->v_type
!= VPORT
) {
711 pp
= VTOEP(fp
->f_vnode
);
713 mutex_enter(&pp
->port_queue
.portq_source_mutex
);
714 ps
= &pp
->port_queue
.portq_scache
[PORT_SHASH(source
)];
715 for (pse
= *ps
; pse
!= NULL
; pse
= pse
->portsrc_next
) {
716 if (pse
->portsrc_source
== source
)
721 /* Create association of the event source with the port */
722 pse
= kmem_zalloc(sizeof (port_source_t
), KM_NOSLEEP
);
724 mutex_exit(&pp
->port_queue
.portq_source_mutex
);
728 pse
->portsrc_source
= source
;
729 pse
->portsrc_close
= port_src_close
;
730 pse
->portsrc_closearg
= arg
;
731 pse
->portsrc_cnt
= 1;
733 pse
->portsrc_next
= (*ps
)->portsrc_next
;
736 /* entry already available, source is only requesting count */
739 mutex_exit(&pp
->port_queue
.portq_source_mutex
);
747 * The port_dissociate_ksource() function dissociates an event source from
751 port_dissociate_ksource(int port
, int source
, port_source_t
*ps
)
760 if ((fp
= getf(port
)) == NULL
)
763 if (fp
->f_vnode
->v_type
!= VPORT
) {
767 pp
= VTOEP(fp
->f_vnode
);
769 mutex_enter(&pp
->port_queue
.portq_source_mutex
);
770 if (--ps
->portsrc_cnt
== 0) {
771 /* last association removed -> free source structure */
772 if (ps
->portsrc_prev
== NULL
) {
774 psh
= &pp
->port_queue
.portq_scache
[PORT_SHASH(source
)];
775 *psh
= ps
->portsrc_next
;
776 if (ps
->portsrc_next
)
777 ps
->portsrc_next
->portsrc_prev
= NULL
;
779 ps
->portsrc_prev
->portsrc_next
= ps
->portsrc_next
;
780 if (ps
->portsrc_next
)
781 ps
->portsrc_next
->portsrc_prev
=
784 kmem_free(ps
, sizeof (port_source_t
));
786 mutex_exit(&pp
->port_queue
.portq_source_mutex
);
792 free_fopdata(vnode_t
*vp
)
796 ASSERT(pvp
->pvp_femp
== NULL
);
797 mutex_destroy(&pvp
->pvp_mutex
);
798 list_destroy(&pvp
->pvp_pfoplist
);
799 kmem_free(pvp
, sizeof (*pvp
));
800 vp
->v_fopdata
= NULL
;