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 (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
26 #ifndef _SYS_SYSEVENT_IMPL_H
27 #define _SYS_SYSEVENT_IMPL_H
29 #include <sys/nvpair.h>
30 #include <sys/id_space.h>
37 typedef uint64_t se_data_t
;
40 * The following data structure assist in loading and extracting event
41 * header and attribute data into contiguous memory. Access to all typed
42 * data done so on 64-bit boundaries. *Do Not* alter any of the structures
43 * defined below without thorough thought and testing.
47 typedef struct se_name
{
50 se_data_t name
; /* 64-bit aligned offset */
54 typedef struct se_value
{
55 int32_t value_type
; /* data type */
57 se_data_t value
; /* data value - 64-bit aligned offset */
60 /* sysevent internal attribute name-value pair stored in contiguous memory */
61 typedef struct sysevent_attr_impl
{
62 int32_t se_attr_sz
; /* Size of attribute data */
63 int32_t se_attr_pad
; /* pad */
64 se_data_t se_attr_name
; /* name of data attribute */
65 se_data_t se_attr_val
; /* value and type of data */
66 } sysevent_attr_impl_t
;
68 /* Attribute list states */
69 #define ATTR_DETACHED 0
70 #define ATTR_ATTACHED 1
73 * The following type definitions describe a sysevent object that is
74 * generated by a call to sysevent_alloc and sent to userland.
78 * sysevent event header information -
79 * contained in every event generated. The header and the event
80 * must remain 64-bit aligned. The header, up to the attribute
81 * offset, can be contained in a single cache line.
83 typedef struct sysevent_hdr
{
84 sysevent_id_t se_id
; /* unique identifier */
85 uint32_t se_version
; /* version of this data structure */
87 uint32_t se_class
; /* event class id - reserved */
88 uint32_t se_subclass
; /* event subclass id - reserved */
89 int32_t se_payload_sz
; /* size of attr data + strings */
90 uint16_t se_subclass_off
; /* offset to subclass string */
91 uint16_t se_pub_off
; /* offset to publisher string */
92 uint64_t se_attr_off
; /* pointer or offset to attr data */
95 /* sysevent event buffer - 64-bit aligned offsets */
96 typedef struct sys_event_impl
{
97 sysevent_hdr_t se_header
;
98 se_data_t se_class_name
; /* class string in contig memory */
99 se_data_t se_subclass_name
; /* subclass string in contig memory */
100 se_data_t se_pub
; /* publisher string in contig mem */
101 se_data_t se_attr_buf
; /* contiguous attribute memory */
104 /* Helpful defines */
105 #define seh_version se_header.se_version
106 #define seh_class se_header.se_class
107 #define seh_subclass se_header.se_subclass
108 #define seh_seq se_header.se_id.eid_seq
109 #define seh_time se_header.se_id.eid_ts
110 #define seh_subclass_off se_header.se_subclass_off
111 #define seh_pub_off se_header.se_pub_off
112 #define seh_attr_off se_header.se_attr_off
113 #define seh_payload_sz se_header.se_payload_sz
114 #define seh_flag se_header.se_flag
116 /* Event buffer version */
117 #define SYS_EVENT_VERSION 0
119 /* Event buffer flags */
120 #define SE_PACKED_BUF 1
122 #define SYSEVENT_IMPL(ev) ((sysevent_impl_t *)(void *)(ev))
123 #define SE_VERSION(ev) (SYSEVENT_IMPL(ev)->seh_version)
124 #define SE_CLASS(ev) (SYSEVENT_IMPL(ev)->seh_class)
125 #define SE_SUBCLASS(ev) (SYSEVENT_IMPL(ev)->seh_subclass)
126 #define SE_SEQ(ev) (SYSEVENT_IMPL(ev)->seh_seq)
127 #define SE_TIME(ev) (SYSEVENT_IMPL(ev)->seh_time)
128 #define SE_SUBCLASS_OFF(ev) (SYSEVENT_IMPL(ev)->seh_subclass_off)
129 #define SE_PUB_OFF(ev) (SYSEVENT_IMPL(ev)->seh_pub_off)
130 #define SE_PAYLOAD_SZ(ev) (SYSEVENT_IMPL(ev)->seh_payload_sz)
131 #define SE_FLAG(ev) (SYSEVENT_IMPL(ev)->seh_flag)
132 #define SE_SIZE(ev) (sizeof (sysevent_impl_t) + SE_PAYLOAD_SZ(ev))
133 #define SE_CLASS_NAME(ev) ((char *)&(SYSEVENT_IMPL(ev)->se_class_name))
134 #define SE_SUBCLASS_NAME(ev) ((char *)((caddr_t)(ev) + SE_SUBCLASS_OFF(ev)))
135 #define SE_PUB_NAME(ev) ((char *)((caddr_t)(ev) + SE_PUB_OFF(ev)))
138 * Attribute data can be stored in contiguous memory or
139 * as a list of attribute data elements. The storage format is determined
140 * by the SE_PACKED_BUF flag in the event buffer flags.
144 /* 64-bit boundary alignment function */
145 #define SE_ALIGN(x) ((((ulong_t)x) + 7ul) & ~7ul)
147 /* Access to unpacked attribute list */
148 #define SE_ATTR_PTR(ev) (SYSEVENT_IMPL(ev)->seh_attr_off)
150 /* Offset to packed attribute data */
151 #define SE_ATTR_OFF(ev) SE_PUB_OFF(ev) + SE_ALIGN(strlen(SE_PUB_NAME(ev)) + 1)
154 #define LOGEVENT_DOOR_UPCALL "/var/run/sysevent_door"
157 * door upcall data structures
159 typedef struct log_event_upcall_arg
{
163 } log_event_upcall_arg_t
;
165 typedef struct log_eventq
{
166 struct log_eventq
*next
;
167 log_event_upcall_arg_t arg
;
170 /* Syseventd Channel structures */
172 #define MAX_CHAN 256 /* Maximum channels per system */
173 #define MAX_SUBSCRIBERS 100 /* Maximum subscribers per channel */
174 #define MAX_PUBLISHERS 1 /* Maximum publishers per channel */
177 * Channel-based subscription structures
180 /* Class hashing defines */
181 #define CLASS_HASH_SZ 63
182 #define CLASS_HASH(class_name) ((hash_func(class_name) \
183 % CLASS_HASH_SZ) + 1)
184 #define CHAN_HASH_SZ 32
186 typedef struct subclass_lst
{
187 struct subclass_lst
*sl_next
;
189 uchar_t sl_num
[MAX_SUBSCRIBERS
+ 1];
192 typedef struct class_lst
{
193 struct class_lst
*cl_next
;
195 struct subclass_lst
*cl_subclass_list
;
198 /* User/Kernel Structure to pass event registration modctl data */
199 typedef struct se_pubsub
{
201 uint32_t ps_channel_name_len
;
208 #define SE_REGISTER 0
209 #define SE_UNREGISTER 1
211 #define SE_OPEN_REGISTRATION 3
212 #define SE_CLOSE_REGISTRATION 4
213 #define SE_BIND_REGISTRATION 5
214 #define SE_UNBIND_REGISTRATION 6
215 #define SE_GET_REGISTRATION 7
222 #define CLASS_NAME "class"
226 typedef struct sysevent_channel_descriptor
{
227 char *scd_channel_name
; /* Name of channel */
228 struct sysevent_channel_descriptor
*scd_next
;
229 int scd_ref_cnt
; /* Reference count of channel opens */
230 id_space_t
*scd_subscriber_cache
; /* cache of subscriber ids */
231 id_space_t
*scd_publisher_cache
; /* cache of publisher ids */
232 uchar_t scd_subscriber_ids
[MAX_SUBSCRIBERS
+ 1]; /* used sub ids */
233 uchar_t scd_publisher_ids
[MAX_PUBLISHERS
+ 1]; /* used pub ids */
234 class_lst_t
*scd_class_list_tbl
[CLASS_HASH_SZ
+ 1];
235 } sysevent_channel_descriptor_t
;
238 * log_sysevent private interfaces
240 extern void log_event_init(void);
241 extern void log_sysevent_flushq(int, uint_t
);
242 extern int log_sysevent_filename(char *);
243 extern int log_usr_sysevent(sysevent_t
*, int, sysevent_id_t
*);
244 extern int log_sysevent_copyout_data(sysevent_id_t
*, size_t, caddr_t
);
245 extern int log_sysevent_free_data(sysevent_id_t
*);
246 extern int log_sysevent_register(char *, char *, se_pubsub_t
*);
247 extern uint64_t log_sysevent_new_id(void);
250 * Structures and definitions for general purpose event channels
254 #define EVCH_MAX_CHANNELS 1024
255 #define EVCH_MAX_BINDS_PER_CHANNEL 512
256 #define EVCH_MAX_SUBSCRIPTIONS 32
257 #define EVCH_SUBPOOLFACT 8
258 #define EVCH_DEFAULT_EVENTS 2000
259 #define EVCH_MAX_TRY_DELIVERY 3
261 /* Linkage element for evch_dlist_t lists */
262 typedef struct evch_dlelem
{
263 struct evch_dlelem
*dl_next
;
264 struct evch_dlelem
*dl_prev
;
269 evch_dlelem_t dh_head
;
273 /* Placeholder for elements in a evch_squeue_t queue */
274 typedef struct evch_qelem
{
275 struct evch_qelem
*q_next
;
280 /* Queue head data */
282 evch_qelem_t
*sq_head
;
283 evch_qelem_t
*sq_tail
;
289 * Defines for event queue routines
292 #define EVQ_DELIVER 2
298 /* Call back routine typedefs */
299 typedef int (*filter_f
)(void *, void *);
300 typedef int (*deliver_f
)(void *, void *);
301 typedef int (*kerndlv_f
)(void *, void *);
302 typedef void (*destr_f
)(void *, void *);
303 typedef int (*compare_f
)(evch_dlelem_t
*, char *);
306 * Event structure handled by evch_evq_* functions. Sysevent type events are
307 * stored as the payload.
310 uint32_t ge_size
; /* Total size of event structure */
311 uint32_t ge_refcount
; /* No of queues event is linked to */
312 destr_f ge_destruct
; /* Destructor for event structure */
313 uint32_t *ge_dstcookie
; /* Cookie for destructor function */
314 uchar_t ge_payload
[1]; /* Placeholder for event data */
318 * Event queue descriptor
321 evch_squeue_t eq_eventq
; /* Protected by eq_dtmutex */
322 kt_did_t eq_thrid
; /* Id delivery thread */
323 kmutex_t eq_queuemx
; /* Protect. of this struct and ev q */
324 kcondvar_t eq_thrsleepcv
; /* Delivery thread sleeps on empty q */
325 int eq_dactive
; /* Event delivery is in progress */
326 kcondvar_t eq_dactivecv
; /* Unsubscr. has to wait on this */
327 evch_dlist_t eq_subscr
; /* Chain of all evch_evqsub_t */
328 uint32_t eq_nsleep
; /* Statistic: Publisher set to sleep */
329 int eq_holdmode
; /* Hold event delivery */
330 evch_gevent_t
*eq_curevent
; /* Event currently beeing delivered */
331 evch_qelem_t
*eq_nextev
; /* For iterating over events in a q */
332 kcondvar_t eq_onholdcv
; /* To signal hold mode of deliv. thr. */
333 uchar_t eq_tabortflag
; /* Request to abort delivery thread */
337 * Event queue per subscriber structure
340 evch_dlelem_t su_link
;
341 filter_f su_filter
; /* Event filter function pointer */
342 void *su_fcookie
; /* cookie for event filter */
343 deliver_f su_callb
; /* Event delivery callback */
344 void *su_cbcookie
; /* callback cookie */
347 /* Eveny delivery type */
348 #define EVCH_DELKERN 1 /* Kernel event delivery */
349 #define EVCH_DELDOOR 2 /* User event delivery via doors */
352 * Per channel subscriber data structure. Chained in a linked list to an
353 * event channel and to a binding.
355 typedef struct chsubd
{
356 evch_dlelem_t sd_link
; /* Links all subscribers of this ch. */
357 struct chsubd
*sd_subnxt
; /* Links all subscr. for a binding */
358 char *sd_ident
; /* Subscriber identifier */
359 evch_eventq_t
*sd_queue
; /* Event queue for this subscriber */
360 evch_evqsub_t
*sd_msub
; /* Main event queue subscr. */
361 char *sd_classname
; /* Filter criteria */
362 size_t sd_clnsize
; /* Size of sd_classname buffer */
363 evch_evqsub_t
*sd_ssub
; /* Subscriber queue subscr. */
364 int sd_type
; /* Type of event delivery */
365 kerndlv_f sd_callback
; /* Callback for kernel delivery */
366 void *sd_cbcookie
; /* Cookie for kernel delivery */
367 door_handle_t sd_door
; /* Door handle for user delivery */
368 int sd_active
; /* Subscription is in use indicator */
369 pid_t sd_pid
; /* PID of subscribing process */
370 uint8_t sd_persist
; /* Persistent user land subscription */
371 uint8_t sd_dump
; /* Dump with sysevent_evc_walk_* */
375 * General purpose event channel descriptor structure. This is the main
376 * structure for event subscribing, publishing, delivery to/from an event
380 evch_dlelem_t ch_link
; /* Must be first elem. of structure */
381 char *ch_name
; /* Channel name */
382 size_t ch_namelen
; /* Length of channel name buffer */
383 kmutex_t ch_mutex
; /* To protect this structure */
384 evch_eventq_t
*ch_queue
; /* Publisher event queue */
385 evch_dlist_t ch_subscr
; /* List of subscr. data (evch_subd_t) */
386 uint32_t ch_bindings
; /* No of bindings to this channel */
387 int ch_maxbinds
; /* Maximum number of binds */
388 uid_t ch_uid
; /* Creators effective user id */
389 gid_t ch_gid
; /* Creators effective group id */
390 kmutex_t ch_pubmx
; /* Mutex for ch_pubcv and ch_nevents */
391 kcondvar_t ch_pubcv
; /* To set publisher to sleep */
392 uint32_t ch_nevents
; /* Current number of events */
393 uint32_t ch_maxev
; /* Maximum number of events */
394 int ch_maxsubscr
; /* Maximum number of subscriptions */
395 int ch_holdpend
; /* Hold pending events mode if != 0 */
396 time_t ch_ctime
; /* Channel creation time */
397 nvlist_t
*ch_propnvl
; /* Channel properties nvlist */
398 int64_t ch_propnvlgen
; /* Properties generation number */
402 * Channel binding structure. Allocated per binding to a channel. Protected
403 * by locking the channel structure
406 evch_chan_t
*bd_channel
;
407 evch_subd_t
*bd_sublst
; /* chain of all subscriptions */
411 * Structure to keep a snapshot of all events of a channel
414 evch_eventq_t
*sn_queue
; /* Event queue with snapshot of ev's */
415 sysevent_impl_t
*sn_nxtev
; /* Pointer to find next event */
418 /* Project private interfaces */
419 extern evchan_t
*evch_usrchanopen(const char *name
, uint32_t flags
, int *err
);
420 extern void evch_usrchanclose(evchan_t
*cbp
);
421 extern sysevent_impl_t
*evch_usrallocev(size_t evsize
, uint32_t flags
);
422 extern void evch_usrfreeev(sysevent_impl_t
*ev
);
423 extern int evch_usrpostevent(evchan_t
*bp
, sysevent_impl_t
*ev
, uint32_t flags
);
424 extern int evch_usrsubscribe(evchan_t
*bp
, const char *sid
, const char *class,
425 int d
, uint32_t flags
);
426 extern int evch_usrcontrol_set(evchan_t
*bp
, int cmd
, uint32_t value
);
427 extern int evch_usrcontrol_get(evchan_t
*bp
, int cmd
, uint32_t *value
);
428 extern void evch_usrunsubscribe(evchan_t
*bp
, const char *subid
, uint32_t flag
);
429 extern int evch_usrgetchnames(char *buf
, size_t size
);
430 extern int evch_usrgetchdata(char *chname
, void *buf
, size_t size
);
431 extern void evch_usrsetpropnvl(evchan_t
*bp
, nvlist_t
*nvl
);
432 extern int evch_usrgetpropnvl(evchan_t
*bp
, nvlist_t
**nvlp
, int64_t *genp
);
434 extern void sysevent_evc_init();
435 extern void sysevent_evc_thrinit();
436 extern evchanq_t
*sysevent_evc_walk_init(evchan_t
*, char *);
437 extern sysevent_t
*sysevent_evc_walk_step(evchanq_t
*);
438 extern void sysevent_evc_walk_fini(evchanq_t
*);
439 extern char *sysevent_evc_event_attr(sysevent_t
*, size_t *);
444 * Structures and limits to deliver channel data to syseventadm
446 #define EVCH_MAX_DATA_SIZE (1024 * 1024)
449 uint32_t sb_nextoff
; /* Offset to next subscr info struct */
450 uint32_t sb_stroff
; /* Offset to strings */
451 uint32_t sb_clnamoff
; /* Offset of class in sb_strings */
452 uint32_t sb_pid
; /* Subscriber process id */
453 uint32_t sb_nevents
; /* Current no of event in sub q */
454 uint32_t sb_evhwm
; /* High watermark of sub q */
455 uint32_t sb_persist
; /* != 0 if subscription persists */
456 uint32_t sb_status
; /* != 0 if subscription is inactive */
457 uint32_t sb_active
; /* > 0 if subscription is in use */
458 uint32_t sb_dump
; /* != 0 if sub will be dumped */
459 char sb_strings
[1]; /* String space for subid and class */
463 uint32_t cd_version
; /* Version of this structure */
464 uint32_t cd_suboffs
; /* Offset of subscriber info struct */
465 uint64_t cd_ctime
; /* Creation time */
466 uint32_t cd_uid
; /* User id */
467 uint32_t cd_gid
; /* Owner group id */
468 uint32_t cd_perms
; /* Permission bits */
469 uint32_t cd_maxev
; /* Max number of events */
470 uint32_t cd_evhwm
; /* High watermark of main event queue */
471 uint32_t cd_nevents
; /* current no of events in main ev q */
472 uint32_t cd_maxsub
; /* Max number of subscriptions */
473 uint32_t cd_nsub
; /* Current number of subscriptions */
474 uint32_t cd_maxbinds
; /* Max number of binds */
475 uint32_t cd_nbinds
; /* Current number of binds */
476 uint32_t cd_holdpend
; /* != 0 when HOLDPEND mode is set */
477 uint32_t cd_limev
; /* Limit of events per channel */
478 sev_subinfo_t cd_subinfo
[1]; /* Per subscriber data */
482 * Project private flags for sysevent_evc_subscribe. Bits 0 to 7 are reserved
483 * for the consolidation private interface, so we must use bits 8-15 here.
485 #define EVCH_SUB_DUMP (0x01 << 8)
490 #define EVCH_PUB 0x0004 /* wants to publish events */
491 #define EVCH_SUB 0x0008 /* wants to subscribe to channel */
493 #define EVCH_SUBU 0x0001 /* Subscribing allowed for uid */
494 #define EVCH_PUBU 0x0002 /* Publishing allowed for uid */
495 #define EVCH_PSUSR 0x0003 /* EVCH_SUBU + EVCH_PUBU */
496 #define EVCH_SUBG 0x0004 /* Subscribing allowed for gid */
497 #define EVCH_PUBG 0x0008 /* Publishing allowed for gid */
498 #define EVCH_PSGRP 0x000C /* EVCH_SUBG + EVCH_PUBG */
499 #define EVCH_SUBO 0x0010 /* Subscribing allowed to all users */
500 #define EVCH_PUBO 0x0020 /* Publishing allowed to all users */
501 #define EVCH_PSOTH 0x0030 /* EVCH_SUBO + EVCH_PUBO */
502 #define EVCH_PSALL 0x003f /* Mask of all permission bits */
505 * Sysevent driver ioctls
507 #define SEV_BASE 0x53455600
508 #define SEV_PUBLISH SEV_BASE | 0x01
509 #define SEV_CHAN_OPEN SEV_BASE | 0x02
510 #define SEV_CHAN_CONTROL SEV_BASE | 0x03
511 #define SEV_SUBSCRIBE SEV_BASE | 0x04
512 #define SEV_UNSUBSCRIBE SEV_BASE | 0x05
513 #define SEV_CHANNAMES SEV_BASE | 0x06
514 #define SEV_CHANDATA SEV_BASE | 0x07
515 #define SEV_SETPROPNVL SEV_BASE | 0x08
516 #define SEV_GETPROPNVL SEV_BASE | 0x09
518 #define DEVSYSEVENT "/dev/sysevent"
519 #define DEVICESYSEVENT "/devices/pseudo/sysevent@0:sysevent"
522 * Maximum allowed binding handles
523 * It's a limit required by bitmap algorithm design (see sys/bitmap.h).
524 * Use pack(4) to make sizeof structs be the same on x86 and amd64.
526 #define SYSEVENT_MINOR_MAX SHRT_MAX
528 #if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
532 /* copyin/copyout data */
534 uint64_t name
; /* pointer to something */
538 typedef struct bind_args
{
543 typedef struct control_args
{
546 } sev_control_args_t
;
548 typedef struct publish_args
{
551 } sev_publish_args_t
;
553 typedef struct subscribe_args
{
555 sev_box_t class_info
;
558 } sev_subscribe_args_t
;
560 typedef struct unsubscribe_args
{
562 } sev_unsubscribe_args_t
;
564 typedef struct chandata
{
567 } sev_chandata_args_t
;
569 typedef struct propnvl_args
{
570 sev_box_t packednvl
; /* input and output */
571 int64_t generation
; /* output on get operation */
572 } sev_propnvl_args_t
;
574 #if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
582 #endif /* _SYS_SYSEVENT_IMPL_H */