diff options
Diffstat (limited to 'usr/src/lib/libsysevent')
| -rw-r--r-- | usr/src/lib/libsysevent/libevchannel.c | 389 | ||||
| -rw-r--r-- | usr/src/lib/libsysevent/libsysevent.c | 27 | ||||
| -rw-r--r-- | usr/src/lib/libsysevent/libsysevent_impl.h | 24 | ||||
| -rw-r--r-- | usr/src/lib/libsysevent/llib-lsysevent | 30 | ||||
| -rw-r--r-- | usr/src/lib/libsysevent/mapfile-vers | 7 |
5 files changed, 406 insertions, 71 deletions
diff --git a/usr/src/lib/libsysevent/libevchannel.c b/usr/src/lib/libsysevent/libevchannel.c index a18a62b0dd..52f9b4641c 100644 --- a/usr/src/lib/libsysevent/libevchannel.c +++ b/usr/src/lib/libsysevent/libevchannel.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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. @@ -20,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <ctype.h> #include <fcntl.h> @@ -35,6 +32,9 @@ #include <stddef.h> #include <stdlib.h> #include <strings.h> +#include <pthread.h> +#include <atomic.h> +#include <signal.h> #include <sys/types.h> #include <sys/varargs.h> #include <sys/sysevent.h> @@ -54,8 +54,34 @@ * sysevent_evc_control - various channel based control operation */ +static void kill_door_servers(evchan_subscr_t *); + #define misaligned(p) ((uintptr_t)(p) & 3) /* 4-byte alignment required */ +static pthread_key_t nrkey = PTHREAD_ONCE_KEY_NP; + +/* + * If the current thread is a door server thread servicing a door created + * for us in sysevent_evc_xsubscribe, then an attempt to unsubscribe from + * within door invocation context on the same channel will deadlock in the + * kernel waiting for our own invocation to complete. Such calls are + * forbidden, and we abort if they are encountered (better than hanging + * unkillably). + * + * We'd like to offer this detection to subscriptions established with + * sysevent_evc_subscribe, but we don't have control over the door service + * threads in that case. Perhaps the fix is to always use door_xcreate + * even for sysevent_evc_subscribe? + */ +static boolean_t +will_deadlock(evchan_t *scp) +{ + evchan_subscr_t *subp = pthread_getspecific(nrkey); + evchan_impl_hdl_t *hdl = EVCHAN_IMPL_HNDL(scp); + + return (subp != NULL && subp->ev_subhead == hdl ? B_TRUE : B_FALSE); +} + /* * Check syntax of a channel name */ @@ -173,14 +199,18 @@ sysevent_evc_bind(const char *channel, evchan_t **scpp, uint32_t flags) /* * sysevent_evc_unbind - Unbind from previously bound/created channel */ -void +int sysevent_evc_unbind(evchan_t *scp) { sev_unsubscribe_args_t uargs; - evchan_subscr_t *subp, *tofree; + evchan_subscr_t *subp; + int errcp; if (scp == NULL || misaligned(scp)) - return; + return (errno = EINVAL); + + if (will_deadlock(scp)) + return (errno = EDEADLK); (void) mutex_lock(EV_LOCK(scp)); @@ -195,19 +225,24 @@ sysevent_evc_unbind(evchan_t *scp) * drained. */ if (ioctl(EV_FD(scp), SEV_UNSUBSCRIBE, (intptr_t)&uargs) != 0) { + errcp = errno; (void) mutex_unlock(EV_LOCK(scp)); - return; + return (errno = errcp); } } - subp = (evchan_subscr_t *)(void*)EV_SUB(scp); - while (subp->evsub_next != NULL) { - tofree = subp->evsub_next; - subp->evsub_next = tofree->evsub_next; - if (door_revoke(tofree->evsub_door_desc) != 0 && errno == EPERM) - (void) close(tofree->evsub_door_desc); - free(tofree->evsub_sid); - free(tofree); + while ((subp = EV_SUB_NEXT(scp)) != NULL) { + EV_SUB_NEXT(scp) = subp->evsub_next; + + /* If door_xcreate was applied we can clean up */ + if (subp->evsub_attr) + kill_door_servers(subp); + + if (door_revoke(subp->evsub_door_desc) != 0 && errno == EPERM) + (void) close(subp->evsub_door_desc); + + free(subp->evsub_sid); + free(subp); } (void) mutex_unlock(EV_LOCK(scp)); @@ -219,6 +254,8 @@ sysevent_evc_unbind(evchan_t *scp) (void) close(EV_FD(scp)); (void) mutex_destroy(EV_LOCK(scp)); free(scp); + + return (0); } /* @@ -287,6 +324,13 @@ door_upcall(void *cookie, char *args, size_t alen, evchan_subscr_t *subp = EVCHAN_SUBSCR(cookie); int rval = 0; + /* + * If we've been invoked simply to kill the thread then + * exit now. + */ + if (subp->evsub_state == EVCHAN_SUB_STATE_CLOSING) + pthread_exit(NULL); + if (args == NULL || alen <= (size_t)0) { /* Skip callback execution */ rval = EINVAL; @@ -304,13 +348,106 @@ door_upcall(void *cookie, char *args, size_t alen, (void) door_return(args, alen, NULL, 0); } +static pthread_once_t xsub_thrattr_once = PTHREAD_ONCE_INIT; +static pthread_attr_t xsub_thrattr; + +static void +xsub_thrattr_init(void) +{ + (void) pthread_attr_init(&xsub_thrattr); + (void) pthread_attr_setdetachstate(&xsub_thrattr, + PTHREAD_CREATE_DETACHED); + (void) pthread_attr_setscope(&xsub_thrattr, PTHREAD_SCOPE_SYSTEM); +} + /* - * sysevent_evc_subscribe - Subscribe to an existing event channel + * Our door server create function is only called during initial + * door_xcreate since we specify DOOR_NO_DEPLETION_CB. */ int -sysevent_evc_subscribe(evchan_t *scp, const char *sid, const char *class, +xsub_door_server_create(door_info_t *dip, void *(*startf)(void *), + void *startfarg, void *cookie) +{ + evchan_subscr_t *subp = EVCHAN_SUBSCR(cookie); + struct sysevent_subattr_impl *xsa = subp->evsub_attr; + pthread_attr_t *thrattr; + sigset_t oset; + int err; + + if (subp->evsub_state == EVCHAN_SUB_STATE_CLOSING) + return (0); /* shouldn't happen, but just in case */ + + /* + * If sysevent_evc_xsubscribe was called electing to use a + * different door server create function then let it take it + * from here. + */ + if (xsa->xs_thrcreate) { + return (xsa->xs_thrcreate(dip, startf, startfarg, + xsa->xs_thrcreate_cookie)); + } + + if (xsa->xs_thrattr == NULL) { + (void) pthread_once(&xsub_thrattr_once, xsub_thrattr_init); + thrattr = &xsub_thrattr; + } else { + thrattr = xsa->xs_thrattr; + } + + (void) pthread_sigmask(SIG_SETMASK, &xsa->xs_sigmask, &oset); + err = pthread_create(NULL, thrattr, startf, startfarg); + (void) pthread_sigmask(SIG_SETMASK, &oset, NULL); + + return (err == 0 ? 1 : -1); +} + +void +xsub_door_server_setup(void *cookie) +{ + evchan_subscr_t *subp = EVCHAN_SUBSCR(cookie); + struct sysevent_subattr_impl *xsa = subp->evsub_attr; + + if (xsa->xs_thrsetup == NULL) { + (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + } + + (void) pthread_setspecific(nrkey, (void *)subp); + + if (xsa->xs_thrsetup) + xsa->xs_thrsetup(xsa->xs_thrsetup_cookie); +} + +/* + * Cause private door server threads to exit. We have already performed the + * unsubscribe ioctl which stops new invocations and waits until all + * existing invocations are complete. So all server threads should be + * blocked in door_return. The door has not yet been revoked. We will + * invoke repeatedly after setting the evsub_state to be noticed on + * wakeup; each invocation will result in the death of one server thread. + * + * You'd think it would be easier to kill these threads, such as through + * pthread_cancel. Unfortunately door_return is not a cancellation point, + * and if you do cancel a thread blocked in door_return the EINTR check in + * the door_return assembly logic causes us to loop with EINTR forever! + */ +static void +kill_door_servers(evchan_subscr_t *subp) +{ + door_arg_t da; + int i; + + bzero(&da, sizeof (da)); + subp->evsub_state = EVCHAN_SUB_STATE_CLOSING; + membar_producer(); + + (void) door_call(subp->evsub_door_desc, &da); +} + +static int +sysevent_evc_subscribe_cmn(evchan_t *scp, const char *sid, const char *class, int (*event_handler)(sysevent_t *ev, void *cookie), - void *cookie, uint32_t flags) + void *cookie, uint32_t flags, struct sysevent_subattr_impl *xsa) { evchan_subscr_t *subp; int upcall_door; @@ -342,6 +479,9 @@ sysevent_evc_subscribe(evchan_t *scp, const char *sid, const char *class, return (errno = EINVAL); } + if (pthread_key_create_once_np(&nrkey, NULL) != 0) + return (errno); /* ENOMEM or EAGAIN */ + /* Create subscriber data */ if ((subp = calloc(1, sizeof (evchan_subscr_t))) == NULL) { return (errno); @@ -361,8 +501,29 @@ sysevent_evc_subscribe(evchan_t *scp, const char *sid, const char *class, class_len = 0; } - upcall_door = door_create(door_upcall, (void *)subp, - DOOR_REFUSE_DESC | DOOR_NO_CANCEL); + /* + * Fill this in now for the xsub_door_server_setup dance + */ + subp->ev_subhead = EVCHAN_IMPL_HNDL(scp); + subp->evsub_state = EVCHAN_SUB_STATE_ACTIVE; + + if (xsa == NULL) { + upcall_door = door_create(door_upcall, (void *)subp, + DOOR_REFUSE_DESC | DOOR_NO_CANCEL); + } else { + subp->evsub_attr = xsa; + + /* + * Create a private door with exactly one thread to + * service the callbacks (the GPEC kernel implementation + * serializes deliveries for each subscriber id). + */ + upcall_door = door_xcreate(door_upcall, (void *)subp, + DOOR_REFUSE_DESC | DOOR_NO_CANCEL | DOOR_NO_DEPLETION_CB, + xsub_door_server_create, xsub_door_server_setup, + (void *)subp, 1); + } + if (upcall_door == -1) { ec = errno; free(subp->evsub_sid); @@ -377,8 +538,6 @@ sysevent_evc_subscribe(evchan_t *scp, const char *sid, const char *class, (void) mutex_lock(EV_LOCK(scp)); - subp->ev_subhead = EVCHAN_IMPL_HNDL(scp); - uargs.sid.name = (uintptr_t)sid; uargs.sid.len = sid_len; uargs.class_info.name = (uintptr_t)class; @@ -388,6 +547,8 @@ sysevent_evc_subscribe(evchan_t *scp, const char *sid, const char *class, if (ioctl(EV_FD(scp), SEV_SUBSCRIBE, (intptr_t)&uargs) != 0) { ec = errno; (void) mutex_unlock(EV_LOCK(scp)); + if (xsa) + kill_door_servers(subp); (void) door_revoke(upcall_door); free(subp->evsub_sid); free(subp); @@ -404,27 +565,145 @@ sysevent_evc_subscribe(evchan_t *scp, const char *sid, const char *class, } /* - * sysevent_evc_unsubscribe - Unsubscribe from an existing event channel + * sysevent_evc_subscribe - subscribe to an existing event channel + * using a non-private door (which will create as many server threads + * as the apparent maximum concurrency requirements suggest). */ +int +sysevent_evc_subscribe(evchan_t *scp, const char *sid, const char *class, + int (*event_handler)(sysevent_t *ev, void *cookie), + void *cookie, uint32_t flags) +{ + return (sysevent_evc_subscribe_cmn(scp, sid, class, event_handler, + cookie, flags, NULL)); +} + +static void +subattr_dfltinit(struct sysevent_subattr_impl *xsa) +{ + (void) sigfillset(&xsa->xs_sigmask); + (void) sigdelset(&xsa->xs_sigmask, SIGABRT); +} + +static struct sysevent_subattr_impl dfltsa; +pthread_once_t dfltsa_inited = PTHREAD_ONCE_INIT; + +static void +init_dfltsa(void) +{ + subattr_dfltinit(&dfltsa); +} + +/* + * sysevent_evc_subscribe - subscribe to an existing event channel + * using a private door with control over thread creation. + */ +int +sysevent_evc_xsubscribe(evchan_t *scp, const char *sid, const char *class, + int (*event_handler)(sysevent_t *ev, void *cookie), + void *cookie, uint32_t flags, sysevent_subattr_t *attr) +{ + struct sysevent_subattr_impl sa; + struct sysevent_subattr_impl *xsa; + + if (attr != NULL) { + xsa = (struct sysevent_subattr_impl *)attr; + } else { + xsa = &dfltsa; + (void) pthread_once(&dfltsa_inited, init_dfltsa); + } + + return (sysevent_evc_subscribe_cmn(scp, sid, class, event_handler, + cookie, flags, xsa)); +} + +sysevent_subattr_t * +sysevent_subattr_alloc(void) +{ + struct sysevent_subattr_impl *xsa = calloc(1, sizeof (*xsa)); + + if (xsa != NULL) + subattr_dfltinit(xsa); + + return (xsa != NULL ? (sysevent_subattr_t *)xsa : NULL); +} + +void +sysevent_subattr_free(sysevent_subattr_t *attr) +{ + struct sysevent_subattr_impl *xsa = + (struct sysevent_subattr_impl *)attr; + + free(xsa); +} + void +sysevent_subattr_thrcreate(sysevent_subattr_t *attr, + door_xcreate_server_func_t *thrcreate, void *cookie) +{ + struct sysevent_subattr_impl *xsa = + (struct sysevent_subattr_impl *)attr; + + xsa->xs_thrcreate = thrcreate; + xsa->xs_thrcreate_cookie = cookie; +} + +void +sysevent_subattr_thrsetup(sysevent_subattr_t *attr, + door_xcreate_thrsetup_func_t *thrsetup, void *cookie) +{ + struct sysevent_subattr_impl *xsa = + (struct sysevent_subattr_impl *)attr; + + xsa->xs_thrsetup = thrsetup; + xsa->xs_thrsetup_cookie = cookie; +} + +void +sysevent_subattr_sigmask(sysevent_subattr_t *attr, sigset_t *set) +{ + struct sysevent_subattr_impl *xsa = + (struct sysevent_subattr_impl *)attr; + + if (set) { + xsa->xs_sigmask = *set; + } else { + (void) sigfillset(&xsa->xs_sigmask); + (void) sigdelset(&xsa->xs_sigmask, SIGABRT); + } +} + +void +sysevent_subattr_thrattr(sysevent_subattr_t *attr, pthread_attr_t *thrattr) +{ + struct sysevent_subattr_impl *xsa = + (struct sysevent_subattr_impl *)attr; + + xsa->xs_thrattr = thrattr; +} + +/* + * sysevent_evc_unsubscribe - Unsubscribe from an existing event channel + */ +int sysevent_evc_unsubscribe(evchan_t *scp, const char *sid) { int all_subscribers = 0; sev_unsubscribe_args_t uargs; - evchan_subscr_t *subp, *tofree; + evchan_subscr_t *subp, *prevsubp, *tofree; + int errcp; int rc; if (scp == NULL || misaligned(scp)) - return; + return (errno = EINVAL); if (sid == NULL || strlen(sid) == 0 || (strlen(sid) >= MAX_SUBID_LEN)) - return; + return (errno = EINVAL); /* No inheritance of binding handles via fork() */ - if (EV_PID(scp) != getpid()) { - return; - } + if (EV_PID(scp) != getpid()) + return (errno = EINVAL); if (strcmp(sid, EVCH_ALLSUB) == 0) { all_subscribers++; @@ -436,6 +715,9 @@ sysevent_evc_unsubscribe(evchan_t *scp, const char *sid) uargs.sid.len = strlen(sid) + 1; } + if (will_deadlock(scp)) + return (errno = EDEADLK); + (void) mutex_lock(EV_LOCK(scp)); /* @@ -444,31 +726,50 @@ sysevent_evc_unsubscribe(evchan_t *scp, const char *sid) rc = ioctl(EV_FD(scp), SEV_UNSUBSCRIBE, (intptr_t)&uargs); if (rc != 0) { + errcp = errno; (void) mutex_unlock(EV_LOCK(scp)); - return; + return (errno = errcp); /* EFAULT, ENXIO, EINVAL possible */ } - /* Search for the matching subscriber */ - subp = (evchan_subscr_t *)(void*)EV_SUB(scp); - while (subp->evsub_next != NULL) { - if (all_subscribers || - (strcmp(subp->evsub_next->evsub_sid, sid) == 0)) { + /* + * Search for the matching subscriber. If EVCH_ALLSUB was specified + * then the ioctl above will have returned 0 even if there are + * no subscriptions, so the initial EV_SUB_NEXT can be NULL. + */ + prevsubp = NULL; + subp = EV_SUB_NEXT(scp); + while (subp != NULL) { + if (all_subscribers || strcmp(subp->evsub_sid, sid) == 0) { + if (prevsubp == NULL) { + EV_SUB_NEXT(scp) = subp->evsub_next; + } else { + prevsubp->evsub_next = subp->evsub_next; + } + + tofree = subp; + subp = subp->evsub_next; + + /* If door_xcreate was applied we can clean up */ + if (tofree->evsub_attr) + kill_door_servers(tofree); - tofree = subp->evsub_next; - subp->evsub_next = tofree->evsub_next; (void) door_revoke(tofree->evsub_door_desc); free(tofree->evsub_sid); free(tofree); - /* Freed single subscriber already */ - if (all_subscribers == 0) { + + /* Freed single subscriber already? */ + if (all_subscribers == 0) break; - } - } else + } else { + prevsubp = subp; subp = subp->evsub_next; + } } (void) mutex_unlock(EV_LOCK(scp)); + + return (0); } /* diff --git a/usr/src/lib/libsysevent/libsysevent.c b/usr/src/lib/libsysevent/libsysevent.c index dc2ebe9858..23cecfd7ad 100644 --- a/usr/src/lib/libsysevent/libsysevent.c +++ b/usr/src/lib/libsysevent/libsysevent.c @@ -20,12 +20,10 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <fcntl.h> #include <errno.h> @@ -103,9 +101,9 @@ sysevent_alloc(char *class, int class_sz, char *subclass, int subclass_sz, aligned_pub_sz = SE_ALIGN(pub_sz); payload_sz = (aligned_class_sz - sizeof (uint64_t)) + - (aligned_subclass_sz - sizeof (uint64_t)) + - (aligned_pub_sz - sizeof (uint64_t)) - sizeof (uint64_t) + - nvlist_sz; + (aligned_subclass_sz - sizeof (uint64_t)) + + (aligned_pub_sz - sizeof (uint64_t)) - sizeof (uint64_t) + + nvlist_sz; /* * Allocate event buffer plus additional payload overhead. @@ -163,8 +161,7 @@ sysevent_post_event(char *class, char *subclass, char *vendor, char *pub_name, } error = modctl(MODEVENTS, (uintptr_t)MODEVENTS_POST_EVENT, - (uintptr_t)ev, (uintptr_t)SE_SIZE(ev), - (uintptr_t)eid, 0); + (uintptr_t)ev, (uintptr_t)SE_SIZE(ev), (uintptr_t)eid, 0); sysevent_free(ev); @@ -692,7 +689,7 @@ se_print(FILE *fp, sysevent_t *ev) (void) sysevent_get_time(ev, &hrt); (void) fprintf(fp, "received sysevent id = 0X%llx:%llx\n", - hrt, (longlong_t)sysevent_get_seq(ev)); + hrt, (longlong_t)sysevent_get_seq(ev)); (void) fprintf(fp, "\tclass = %s\n", sysevent_get_class_name(ev)); (void) fprintf(fp, "\tsubclass = %s\n", sysevent_get_subclass_name(ev)); if ((vendor = sysevent_get_vendor_name(ev)) != NULL) { @@ -807,6 +804,7 @@ struct reg_args { * is called in response to a door call to post an event. * */ +/*ARGSUSED*/ static void event_deliver_service(void *cookie, char *args, size_t alen, door_desc_t *ddp, uint_t ndid) @@ -1087,6 +1085,7 @@ dealloc_subscribers(sysevent_handle_t *shp) } } +/*ARGSUSED*/ static int alloc_subscriber(sysevent_handle_t *shp, uint32_t sub_id, int oflag) { @@ -1470,6 +1469,7 @@ create_failed: * is called in response to a registration cache update. * */ +/*ARGSUSED*/ static void cache_update_service(void *cookie, char *args, size_t alen, door_desc_t *ddp, uint_t ndid) @@ -1490,6 +1490,7 @@ cache_update_service(void *cookie, char *args, size_t alen, goto return_from_door; } + /* LINTED: E_BAD_PTR_CAST_ALIGN */ rargs = (struct reg_args *)args; shp = (sysevent_handle_t *)cookie; @@ -1833,8 +1834,8 @@ sysevent_open_channel(const char *channel) while (getextmntent(fp, &m, sizeof (struct extmnttab)) == 0) { if (strcmp(m.mnt_mountp, "/var/run") == 0 && - strcmp(m.mnt_fstype, "tmpfs") == 0) { - (void) fclose(fp); + strcmp(m.mnt_fstype, "tmpfs") == 0) { + (void) fclose(fp); var_run_mounted = 1; break; } @@ -2127,7 +2128,7 @@ sysevent_bind_subscriber(sysevent_handle_t *shp, if ((SH_DOOR_DESC(shp) = door_create(event_deliver_service, (void *)shp, DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) { dprint("sysevent_bind_subscriber: door create failed: " - "%s\n", strerror(errno)); + "%s\n", strerror(errno)); error = EFAULT; goto fail; } @@ -2154,7 +2155,7 @@ sysevent_bind_subscriber(sysevent_handle_t *shp, /* Create an event handler thread */ if (thr_create(NULL, NULL, (void *(*)(void *))subscriber_event_handler, - shp, THR_BOUND, &sub_info->sp_handler_tid) != 0) { + shp, THR_BOUND, &sub_info->sp_handler_tid) != 0) { error = EFAULT; goto fail; } diff --git a/usr/src/lib/libsysevent/libsysevent_impl.h b/usr/src/lib/libsysevent/libsysevent_impl.h index 7d02359212..edd6988169 100644 --- a/usr/src/lib/libsysevent/libsysevent_impl.h +++ b/usr/src/lib/libsysevent/libsysevent_impl.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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. @@ -19,16 +18,15 @@ * * CDDL HEADER END */ + /* - * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _LIBSYSEVENT_IMPL_H #define _LIBSYSEVENT_IMPL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -137,6 +135,15 @@ typedef struct evchan_impl_handle { #define EV_SUB(evcp) (&(EVCHAN_IMPL_HNDL(evcp)->ev_sub)) #define EV_SUB_NEXT(evcp) (EVCHAN_IMPL_HNDL(evcp)->ev_sub.evchan_sub_next) +struct sysevent_subattr_impl { + door_xcreate_server_func_t *xs_thrcreate; + void *xs_thrcreate_cookie; + door_xcreate_thrsetup_func_t *xs_thrsetup; + void *xs_thrsetup_cookie; + pthread_attr_t *xs_thrattr; + sigset_t xs_sigmask; +}; + /* * Subscriber private data */ @@ -147,8 +154,13 @@ struct evchan_subscriber { char *evsub_sid; /* identifier of subscriber */ void *evsub_cookie; /* subscriber cookie */ int (*evsub_func)(sysevent_t *, void *); /* subscriber event handler */ + struct sysevent_subattr_impl *evsub_attr; + uint32_t evsub_state; }; +#define EVCHAN_SUB_STATE_ACTIVE 1 +#define EVCHAN_SUB_STATE_CLOSING 2 + /* Access to subscriber data */ #define EVCHAN_SUBSCR(subp) ((evchan_subscr_t *)(subp)) diff --git a/usr/src/lib/libsysevent/llib-lsysevent b/usr/src/lib/libsysevent/llib-lsysevent index 848135ec67..a0cc48b012 100644 --- a/usr/src/lib/libsysevent/llib-lsysevent +++ b/usr/src/lib/libsysevent/llib-lsysevent @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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. @@ -22,14 +21,12 @@ /*LINTLIBRARY*/ /*PROTOLIB1*/ /* - * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * usr/src/lib/libsysevent/llib-lsysevent */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <synch.h> #include <thread.h> #include "libsysevent.h" @@ -118,7 +115,7 @@ void se_print(FILE *fp, sysevent_t *ev); int sysevent_evc_bind(const char *channel_path, evchan_t **scpp, uint32_t flags); -void sysevent_evc_unbind(evchan_t *scp); +int sysevent_evc_unbind(evchan_t *scp); int sysevent_evc_publish(evchan_t *scp, const char *event_class, const char *event_subclass, const char *vendor, const char *pub_name, @@ -128,7 +125,24 @@ int sysevent_evc_subscribe(evchan_t *scp, const char *sid, const char *event_class, int (*event_handler)(sysevent_t *ev, void *cookie), void *cookie, uint32_t flags); +int sysevent_evc_xsubscribe(evchan_t *scp, const char *sid, + const char *event_class, + int (*event_handler)(sysevent_t *ev, void *cookie), + void *cookie, uint32_t flags, + sysevent_subattr_t *xs); -void sysevent_evc_unsubscribe(evchan_t *scp, const char *sid); +int sysevent_evc_unsubscribe(evchan_t *scp, const char *sid); int sysevent_evc_control(evchan_t *scp, int cmd, ...); + +sysevent_subattr_t *sysevent_subattr_alloc(void); +void sysevent_subattr_free(sysevent_subattr_t *attr); + +void sysevent_subattr_thrcreate(sysevent_subattr_t *attr, + door_xcreate_server_func_t *func, void *cookie); +void sysevent_subattr_thrsetup(sysevent_subattr_t *attr, + door_xcreate_thrsetup_func_t *func, void *cookie); + +void sysevent_subattr_thrattr(sysevent_subattr_t *attr, + pthread_attr_t *thrattr); + diff --git a/usr/src/lib/libsysevent/mapfile-vers b/usr/src/lib/libsysevent/mapfile-vers index e9fb12a36d..7e4107db31 100644 --- a/usr/src/lib/libsysevent/mapfile-vers +++ b/usr/src/lib/libsysevent/mapfile-vers @@ -84,6 +84,7 @@ SUNWprivate_1.1 { sysevent_evc_subscribe; sysevent_evc_unbind; sysevent_evc_unsubscribe; + sysevent_evc_xsubscribe; sysevent_get_class; sysevent_get_pub; sysevent_get_subclass; @@ -95,6 +96,12 @@ SUNWprivate_1.1 { sysevent_unbind_publisher; sysevent_unbind_subscriber; sysevent_unregister_event; + sysevent_subattr_alloc; + sysevent_subattr_free; + sysevent_subattr_sigmask; + sysevent_subattr_thrattr; + sysevent_subattr_thrcreate; + sysevent_subattr_thrsetup; local: *; }; |
