summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsysevent
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libsysevent')
-rw-r--r--usr/src/lib/libsysevent/libevchannel.c389
-rw-r--r--usr/src/lib/libsysevent/libsysevent.c27
-rw-r--r--usr/src/lib/libsysevent/libsysevent_impl.h24
-rw-r--r--usr/src/lib/libsysevent/llib-lsysevent30
-rw-r--r--usr/src/lib/libsysevent/mapfile-vers7
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:
*;
};