|
|
1.1 root 1: #ifndef __KERNEL_STRMLIB_H__
2: #define __KERNEL_STRMLIB_H__
3:
4: /*
5: * This ^^^^^^^^^^^^^^^^^ symbol is used in the DDI/DKI header <sys/ddi.h> to
6: * determine which #undef directives it is required to perform, on the basis
7: * that it should avoid touching namespaces unless they have been reserved
8: * by the inclusion of a header which reserves such classes of names.
9: */
10:
11: /*
12: * This file contains definitions that are be used for the implementation of
13: * the STREAMS standard library routines and scheduling code. Some details
14: * of the interfaces between STREAMS and the rest of the system will also
15: * be dealt with here so as to insulate the STREAMS implementation from the
16: * details of that interface.
17: *
18: * Note that as the contents of this header are for private, system internal
19: * use only, names do not begin with underscores.
20: */
21:
22: /*
23: *-IMPORTS:
24: * <common/ccompat.h>
25: * __EXTERN_C_BEGIN__
26: * __EXTERN_C_END__
27: * __PROTO ()
28: * <common/xdebug.h>
29: * __LOCAL__
30: * <common/__size.h>
31: * __size_t
32: * <common/__clock.h>
33: * __clock_t
34: * <common/__pid.h>
35: * __pid_t
36: * <kernel/st_alloc.h>
37: * _ST_HEAP_CONTROL
38: * <kernel/defer.h>
39: * defer_int_any ()
40: * <sys/ksynch.h>
41: * lock_t
42: * sv_t
43: * <sys/uio.h>
44: * uio_t
45: */
46:
47: #include <common/ccompat.h>
48: #include <common/xdebug.h>
49: #include <common/__size.h>
50: #include <common/__clock.h>
51: #include <common/__pid.h>
52: #include <kernel/st_alloc.h>
53: #include <kernel/defer.h>
54: #include <sys/inline.h>
55: #include <sys/ksynch.h>
56: #include <sys/uio.h>
57:
58: #include <common/_stream.h>
59: #include <kernel/ddi_lock.h>
60: #include <kernel/ddi_glob.h>
61:
62: /*
63: * In order to be able to declare prototypes that refer to structures that are
64: * declared in other headers, we supply incomplete declarations at top-level
65: * to avoid some scoping problems.
66: */
67:
68: struct stroptions;
69: struct strbuf;
70:
71:
72: /*
73: * In onder for freezestr () to work as defined in the Multiprocessor DDI/DKI,
74: * it cannot simply be implemented in terms of the high-level locking
75: * operations defined in <sys/ksynch.h> (the reason being that it is specified
76: * as raising the processor priority level, whereas the "pl" parameter to the
77: * high-level locking functions is specified as setting the level, with a
78: * caution that it not cause the level to be lowered).
79: *
80: * Stream queue freezing cannot really be implemented in terms of high-level
81: * basic locks because of the hierarchy mechanism; the relative priority of
82: * stream head locks is determined by relative position in a stream so that
83: * following the "q_next" member yields increasing (virtual) hierarchy values,
84: * with the additional constraint that a given context may only hold a lock on
85: * one side of a stream at a time.
86: */
87:
88: #define SFREEZE_INIT(q) ((void) ATOMIC_CLEAR_UCHAR ((q)->q_locked))
89: #define SFREEZE_DESTROY(q) ((void) 0)
90: #define SFREEZE_LOCK(q,name) TEST_AND_SET_LOCK ((q)->q_locked, plstr, \
91: (name))
92: #define SFREEZE_UNLOCK(q,pl) (ATOMIC_CLEAR_UCHAR ((q)->q_locked), \
93: (void) splx (pl))
94: #define SFREEZE_ASSERT_FROZEN(q) ASSERT (ATOMIC_FETCH_UCHAR ((q)->q_locked))
95:
96:
97: /*
98: * The implementation of allocb () and freeb () deals in terms of "triples"
99: * consisting of an mblk_t, a dblk_t, and the actual data being managed.
100: * (Of course, under esballoc () the data belongs to another subsystem, but
101: * such a double should also be managed by the same system).
102: *
103: * Be aware that changing the definition of any of these things may
104: * invalidate assumptions made by the code in allocb (), freeb (), dupb ()
105: * and esballoc ().
106: */
107:
108: /*
109: * Various ways to map between the components of a triple.
110: */
111:
112: #define MB_TO_DB(mp) ((dblk_t *) (mp + 1))
113: #define DB_TO_MB(db) (((mblk_t *) db) - 1)
114: #define DB_TO_DATA(db) ((unsigned char *) (db + 1))
115: #define DATA_TO_DB(d) (((dblk_t *) d)) - 1)
116:
117:
118: /*
119: * Some useful predicates for determining whether various items are actually
120: * parts of triples or not, since there are exceptional cases where the
121: * individual elements of a triple have been scattered to the four winds.
122: *
123: * Note that the SET_MB_TRIPLE () and SET_MB_FREE () exist as a pair, since
124: * they only relate to message blocks that are part of a triple.
125: * SET_MB_TRIPLE () is used when a message block is instantiated, and
126: * SET_MB_FREE () is used when a message block is deallocated but the rest
127: * of the triple is still in use.
128: */
129:
130: #define IS_DB_USER_DATA(db) (db->db_base != DB_TO_DATA (db))
131: /*
132: * Test to see whether the
133: * data referenced by this
134: * block is user-controlled.
135: */
136:
137: #define IS_TRIPLE_TOGETHER(mp) (mp->b_datap == MB_TO_DB (mp))
138: /*
139: * Test to see whether the
140: * data block referenced by
141: * this message block forms
142: * part of the same triple.
143: */
144:
145: #define SET_MB_TRIPLE(mp) (void) ((mp)->b_flags =\
146: ((mp)->b_flags | MSGTRIPLE) & ~ MSGFREE)
147: /*
148: * Mark the message block as
149: * part of a triple.
150: */
151:
152: #define IS_MB_TRIPLE(mp) (((mp)->b_flags & MSGTRIPLE) != 0)
153: /*
154: * Test whether the message
155: * block is part of a triple
156: * or is a floating block.
157: */
158:
159: #define SET_MB_FREE(mp) (void) ((mp)->b_flags |= MSGFREE)
160: /*
161: * Indicate that the message
162: * block is no longer in
163: * use. Only for message
164: * blocks in triples.
165: */
166:
167: #define IS_MB_FREE(mp) ((mp->b_flags & MSGFREE) != 0)
168: /*
169: * Test whether the message
170: * block is free or not.
171: */
172:
173: /*
174: * STREAMS Local extension: scheduling
175: */
176:
177: /*
178: * The methods used in the multiplexing examples in the STREAMS Programmer's
179: * Guide for System V Release 2 are quite inefficient. The following general
180: * STREAMS queue scheduling structures and routines were defined in a visible
181: * manner since
182: *
183: * (i) It served to better-document the way in which queues are serviced
184: * within this STREAMS implementation,
185: *
186: * (ii) Multiplexing drivers (and device drivers which multiplex several
187: * minor numbers on a single I/O bus, such as an Ethernet or SCSI
188: * driver) need effcient mechanisms for managing multiple request
189: * channels,
190: *
191: * (iii) It allows drivers to leverage the multiprocessor locking that is
192: * built into these primitives.
193: *
194: * Note that allowing drivers access to this facility causes a significant
195: * departure from the standard version of STREAMS, but that driver use of the
196: * macros and data structures below permits other implementations.
197: *
198: * As this system is used internally by this STREAMS implementation, it can
199: * use the "q_link" member of a queue to hold a link to the next STREAM on
200: * a schedule. In addition, some "q_flag" bits can be used to control
201: * whether or not a queue is currently threaded on any schedule. A portable
202: * implementation that does not depend on any reserved parts of STREAMS
203: * data structures may not use these fields, and so may operate under a
204: * different set of constraints. However, since in this case the drivers and
205: * STREAMS itself share common scheduling code, the following restrictions
206: * must be observed:
207: *
208: * (i) A queue may be requested to be scheduled more than once with no
209: * effect. If a queue is requested to be scheduled on different
210: * schedules, then this is probably an error, most likely to occur
211: * if you define both a STREAMS service routine and a schedule for
212: * a driver queue; this should not be done under the common scheme.
213: *
214: * (ii) A queue which has noenable () set on it will still be scheduled.
215: * The manner in which qenable ()/noenable () work has no bearing on
216: * this mechanism.
217: *
218: * (iii) Schedules should only be created or destroyed with the schedule
219: * allocation/deallocation routines in order to guarantee that the
220: * schedule is multi-processor addressable and is the correct size for
221: * the selected run-time environment.
222: *
223: * (iv) When a driver is closed, the queue must not be on any schedule in
224: * order to prevent list corruption and the dire effects that can
225: * result from such corruption. A portable implementation of scheduling
226: * has no way to do this automatically for the driver since the
227: * close () call is managed by STREAMS.
228: *
229: * Note that in this common implementation, conditions (i), (iii), and (iv)
230: * can be checked by the scheduling system if compiled such that debugging
231: * code is inserted.
232: */
233:
234: /*
235: * STREAMS scheduler private per-schedule global data structure.
236: */
237:
238: struct __streams_schedule {
239: queue_t * ss_head; /* head of list of scheduled queues */
240: queue_t * ss_tail; /* tail of list of scheduled queues */
241:
242: lock_t * ss_locked; /* lock for schedule */
243: };
244:
245:
246: extern lkinfo_t __stream_schedule_lkinfo;
247:
248: #define SCHLOCK_INIT(s,flag) \
249: ((s)->ss_locked = LOCK_ALLOC (stream_schedule_hierarchy, plstr, \
250: & __stream_schedule_lkinfo, (flag)))
251:
252: #define SCHLOCK_DESTROY(s) LOCK_DEALLOC ((s)->ss_locked)
253:
254: #define SCHLOCK_LOCK(s,n) LOCK ((s)->ss_locked, plstr)
255:
256: #define SCHLOCK_UNLOCK(s,p) UNLOCK ((s)->ss_locked, p)
257:
258: #define SCHLOCK_ASSERT_LOCKED(s) \
259: ASSERT (TRYLOCK ((s)->ss_locked, plstr) == invpl)
260:
261: #define SCHED_INIT(s,flag) ((s)->ss_head = (s)->ss_tail = NULL, \
262: SCHLOCK_INIT (s, flag))
263:
264:
265: /*
266: * I use these everywhere that I know which queue side I've got. These
267: * macros duplicate the old-style RD () and WR () functionality, which has
268: * been changed along the path from System V Release 3.2 to System V Release
269: * 4 Multi-Processor. When compiling under the DDI/DKI, these macros are also
270: * converted to functions.
271: */
272:
273: #define W(q) ((q) + 1)
274: #define R(q) ((q) - 1)
275:
276:
277: /*
278: * A utility function, for use with STRMEM_ALLOC (), to calculate the size
279: * required for a message triple with "n" bytes of associated data buffer.
280: */
281:
282: #define MSGB_SIZE(n) ((n) + sizeof (mblk_t) + sizeof (dblk_t))
283:
284:
285: /*
286: * The following data type is used to hold registration information for the
287: * SIGPOLL signal. Every process that registers for SIGPOLL signals allocates
288: * one of these structures and threads it on the stream head.
289: */
290:
291: typedef struct sigpoll sigpoll_t;
292:
293:
294: /*
295: * The following is the internal structure (an "event cell" in STREAMS)
296: * used by the bufcall ()/esbbcall () mechanism to record the necessary
297: * information for calling the user back.
298: *
299: * Note that the real System V bufcall ()/esbbcall () takes a a pointer to
300: * a function with undefined parameters, yet also accepts a parameter which
301: * it will then pass on to the callback. The only way to implement this at
302: * all portably is to use some version of the ISO <stdarg.h> mechanism to
303: * allow bufcall () to take any argument in it's "natural" form and then
304: * pass a maximum-sized chunk of stack into the callback in order to capture
305: * all of the information that the client wanted to pass.
306: *
307: * Of course, doing this is opening a wide door to all kinds of problems,
308: * since while there are some sleazy ways to restrict the size of the extra
309: * argument to something reasonable, there is no way that we can make sure
310: * that the shapes of the argument and the callback parameter really do
311: * match (eg, the callback takes a long but bufcall () is given an int).
312: *
313: * Of course, this is all no worse than the situation AT&T have under the
314: * DDI/DKI, where bufcall () is required to take the callback parameter as
315: * a "long" and clients assume that pointers have the same shape as longs
316: * (if you look at the example in bufcall (D3DK) that is exactly what A&T
317: * seem to be suggesting - blech).
318: *
319: * There is no entirely satisfactory way to get around this evil in plain C,
320: * although we can get at least a partial solution through supplying a range
321: * of supplementary definitions that (at least in an ISO environment) ensure
322: * that the function argument types and argument types will be coerced to
323: * something reasonable.
324: *
325: * Event management is made a little more complex by the availability of the
326: * unbufcall () procedure, which requires us to assign a numeric ID code to
327: * each event cell. It would be nice if this ID code also included some kind
328: * of generation field, and mapped instantly to the desired value.
329: *
330: * Note that this is exactly the same problem faced by the timeout () routine
331: * in implementing untimeout (), and there are numerous possible solutions,
332: * each of which maximizes some desirable property at the cost of losing some
333: * other property.
334: */
335:
336: #define _TOID_MEMBER 1
337:
338: typedef void (* se_funcptr_t) __PROTO ((long _arg));
339:
340: typedef struct __stream_event sevent_t;
341:
342: struct __stream_event {
343: sevent_t * se_next; /* next event in chain */
344: sevent_t * se_prev; /* previous event in chain */
345: long se_arg; /* argument for function */
346: se_funcptr_t se_func; /* function to call */
347: unsigned int se_size; /* optional size information */
348: #if _TOID_MEMBER
349: toid_t se_id; /* timeout id for item */
350: #endif
351: };
352:
353:
354: /*
355: * Of course, we have to thread the above events on a list. We'll create a
356: * structure for this to abstract the details of the locking scheme we'll use
357: * for maintaining the consistency of the event lists.
358: *
359: * We store a generator for the timeout ID codes in the list header so that
360: * the ID generation step can be protected by the same lock as the list
361: * manipulation code. This means that at initialisation time each list header
362: * should have the initial ID code set to its number and that the increment
363: * value used to step between codes is one greater than the total number of
364: * list headers (so that code 0 never appears).
365: *
366: * We have a wide range of possible policies for managing event cells. We need
367: * to get some performance data on each to make a final decision.
368: */
369:
370: #define _FIFO_BUFCALL 1
371:
372: typedef struct __stream_event_list selist_t;
373:
374: struct __stream_event_list {
375: lock_t * sl_locked;
376: sevent_t * sl_head;
377: #if _FIFO_BUFCALL
378: sevent_t * sl_tail;
379: #endif
380: #if _TOID_MEMBER
381: toid_t sl_id;
382: #endif
383: };
384:
385:
386: extern lkinfo_t __stream_event_lkinfo;
387:
388: #define SELIST_INIT(s,flag) \
389: ((s)->sl_head = NULL, \
390: (s)->sl_locked = LOCK_ALLOC (stream_event_hierarchy, plstr, \
391: & __stream_event_lkinfo, (flag)))
392:
393: #define SELIST_DESTROY(s) LOCK_DEALLOC ((s)->sl_locked)
394:
395: #define SELIST_LOCK(s) LOCK ((s)->sl_locked, plstr)
396:
397: #define SELIST_UNLOCK(s,pl) UNLOCK ((s)->sl_locked, (pl))
398:
399: #define SELIST_ASSERT_LOCKED(s) \
400: ASSERT (TRYLOCK ((s)->sl_locked, plstr) == invpl)
401:
402:
403: /*
404: * Some handy requirements for timeout ID generation. We have to define these
405: * numbers such that each list above generates a non-overlapping sequence that
406: * overflows into the same sequence, eg.
407: * 1, k + 1, 2k + 1, ... ik + 1, 1, ...
408: * 2, k + 2, 2k + 2, ... ik + 2, 2, ...
409: *
410: * Since each list generates a distinct and identifiable sequence we can map
411: * from the ID to the list in one step, which somewhat ameliorates the cost
412: * of having to search the list to find the given event.
413: */
414:
415: #define TOID_INCREMENT (N_PRI_LEVELS + 1)
416: #define TOID_MODULUS (TOID_MAX - TOID_MAX % TOID_INCREMENT)
417: #define TOID_TO_PRI(id) ((id) % TOID_INCREMENT - 1)
418:
419:
420: /*
421: * Watermark control structures:
422: *
423: * We record here the amount of memory held by each allocation band and the
424: * maximum amount we will permit it to hold. In addition, we record a thread
425: * of structures used by bufcall () and esbbcall () to record information
426: * for callbacks to drivers when memory becomes available.
427: */
428: /*
429: * A note on bufcall ()/esbbcall () structures;
430: *
431: * I am not able to conceive of a comprehensive strategy for dealing with
432: * these things that works well under all circumstances. For now, it seems
433: * that keeping a few around in preallocated event cells is a good idea for
434: * when we run out of memory. However, as long as possible the system will
435: * always attempt to satisfy a request for an event cell with a newly
436: * allocated cell, since we expect the usual reason for being unable to
437: * satisfy a request is that memory is merely fragmented rather than fully
438: * occupied.
439: *
440: * Of course, allocating bufcall cells within the heap may increase the
441: * level of fragmentation - which is why we prefer to allocate them from
442: * the "long-term" heap (and indeed, why we have two heaps at all).
443: */
444:
445: #define N_PRI_LEVELS 3 /*
446: * Number of buffer priority levels
447: */
448: #define MAP_PRI_LEVEL(p) p /*
449: * Map from BPRI_xxx to index.
450: */
451:
452: /* #define SPLIT_STREAMS_MEMORY */ /*
453: * Control whether there are separate
454: * arenas for messages and other
455: * allocations.
456: */
457:
458: /*
459: * We keep several lists of stream heads according to the category of the
460: * stream; device, pipe, and possibly FIFO. Various general operations require
461: * iterating over several of the lists, and so we define an array of list
462: * head pointers to simplify things since we don't have the C++ "pointer to
463: * member" types and operations available.
464: */
465:
466: typedef struct __stream_head shead_t;
467:
468: typedef enum slist_id {
469: DEV_SLIST,
470: PIPE_SLIST,
471: SLIST_MAX
472: } slist_id_t;
473:
474: typedef int muxid_t;
475:
476:
477: /*
478: * This structure grew to its present form before the <kernel/ddi_glob.h>
479: * header took shape. Most of it should eventually be moved there, with
480: * appropriate thought given to what should be fixed and what should be
481: * variable allocations.
482: */
483:
484:
485: struct streams_mem {
486: atomic_uchar_t sm_init; /* primitive lock for startup */
487:
488: __size_t sm_used; /* memory used in the message heap */
489: __size_t sm_max [N_PRI_LEVELS];
490: /*
491: * Maximum memory we let a level use
492: */
493:
494: toid_t sm_bcid; /* id generator for bufcall events */
495: selist_t sm_bcevents [N_PRI_LEVELS];
496: /*
497: * Bufcall event linked-list head.
498: */
499: ssched_t sm_sched [1]; /* List of enabled queues. */
500:
501: lock_t * sm_seq_lock; /* Lock sequence number registers. */
502: unsigned long sm_err_seq; /* error log sequence number */
503: unsigned long sm_trc_seq; /* trace log sequence number */
504: unsigned long sm_con_seq; /* console log sequence number */
505:
506: queue_t * sm_log_rq; /* STREAMS logger device */
507:
508: lock_t * sm_proc_lock; /* Basic lock for qprocsoff (). */
509: sv_t * sm_proc_sv; /*
510: * Synchronization variable for
511: * qprocsoff ().
512: */
513: queue_t * sm_log_drvr; /* Log-driver read side. */
514:
515: rwlock_t * sm_head_lock; /* Lock for stream head list */
516: shead_t * sm_streams [SLIST_MAX];
517: /* Chains of stream heads */
518:
519: __size_t sm_maxctlsize; /* max. size of control message */
520: __size_t sm_maxdatasize; /* max. size of data message part */
521:
522:
523: /*---------- Locked by sm_msg_lock ------------*/
524: lock_t * sm_msg_lock; /* basic lock for message heap */
525: _ST_HEAP_CONTROL_P sm_msg_heap; /* Memory heap for STREAMS messages */
526: sv_t * sm_msg_sv; /*
527: * synchronization variable for
528: * waiting for free memory.
529: */
530: __size_t sm_msg_needed; /* Level of free memory required */
531:
532: #ifdef SPLIT_STREAMS_MEMORY
533: /*---------- Locked by sm_other_lock ------------*/
534:
535: lock_t * sm_other_lock; /* basic lock for "other" heap */
536:
537: _ST_HEAP_CONTROL_P sm_other_heap;/* Memory heap for long-term info */
538:
539: sv_t * sm_other_sv; /*
540: * synchronization variable for
541: * waiting for free memory.
542: */
543: __size_t sm_other_needed;/* Level of free memory required */
544: #else
545: # define sm_other_heap sm_msg_heap
546: # define sm_other_lock sm_msg_lock
547: # define sm_other_sv sm_msg_sv
548: # define sm_other_needed sm_msg_needed
549: #endif
550: };
551:
552:
553: /*
554: * These should be the standard priorities to be used with the locks for
555: * controlling access to the various memory pools.
556: */
557:
558: #ifdef SPLIT_STREAMS_MEMORY
559:
560: # define str_msg_pl plstr
561: # define str_other_pl plhi
562:
563: #else
564:
565: # define str_msg_pl plhi
566: # define str_other_pl plhi
567:
568: #endif
569:
570:
571: /*
572: * When someone thinks it might be a good idea to see about running some of
573: * the bufcall routines, we defer a routine to deal with the checking. A
574: * global flag bit protects
575: */
576:
577: #define SCHEDULE_BUFCALLS() \
578: (ATOMIC_FETCH_AND_STORE_UCHAR (ddi_global_data ()->dg_run_bufcalls, 1) \
579: == 1 ? (void) 0 : (void) defer_int_any (RUN_BUFCALLS))
580:
581:
582: /*
583: * If all allocations are coming from the same pool, non-message allocations
584: * need to be counted in with the allocation-priority information.
585: *
586: * The "other" pool (which will really be the message pool) should be locked
587: * when these functions are called.
588: */
589:
590: #ifdef SPLIT_STREAMS_MEMORY
591:
592: # define OTHER_ALLOCED(size)
593: # define OTHER_FREED(size)
594:
595: #else
596:
597: # define OTHER_ALLOCED(size) (void) (str_mem->sm_used += size)
598: # define OTHER_FREED(size) ((void) (str_mem->sm_used -= size), \
599: SCHEDULE_BUFCALLS ())
600:
601: #endif
602:
603:
604: /*
605: * We need access to a global instance of the above for managing STREAMS
606: * memory in a consistent manner.
607: */
608:
609: extern struct streams_mem str_mem [];
610:
611:
612: /*
613: * Category flags for the sh_lock_mask member. This is a collection of flag
614: * bits which correspond to operations on the "sh_wait_sv" synchronization
615: * variable.
616: */
617:
618: typedef enum category {
619: SH_NONE = 0, /* use for paranoid checking */
620: SH_OPENCLOSE = 1,
621: SH_IOCTL_LOCK = 2,
622: SH_READ_LOCK = 4, /* NOT NORMALLY USED */
623: SH_WRITE_LOCK = 8, /* NOT NORMALLY USED */
624: SH_PEEK_LOCK = 16,
625:
626: SH_LOCK_MASK = 31, /* Mask for lock bits */
627:
628:
629: SH_READ_WAIT = 32,
630: SH_WRITE_WAIT = 64,
631: SH_IOCTL_WAIT = 128,
632: SH_DRAIN_WAIT = 256,
633: SH_PEEK_WAIT = 512,
634:
635: SH_WAIT_MASK = 992, /* Mask for wait bits */
636:
637:
638: /*
639: * Not a lock mask; just use the extra flag space.
640: */
641:
642: SH_TIMEFLAG = 8192
643: } cat_t;
644:
645:
646: /*
647: * Stream head control structure.
648: *
649: * Be careful with locking the stream head; for many operations, it may be
650: * sufficient to freeze the stream head.
651: */
652:
653: struct __stream_head {
654: n_dev_t sh_dev; /* key for lookup */
655: shead_t * sh_next; /* next stream head on chain */
656:
657: queue_t * sh_head; /* read queue of stream head */
658: struct streamtab
659: * sh_tab; /* initialisation data for driver */
660:
661: __clock_t sh_cltime; /* time to wait for close to drain */
662:
663: struct pollhead
664: * sh_pollhead; /* for polling support */
665:
666: pid_t sh_pgrp; /* foreground TTY process group */
667: __VOID__ * sh_controller; /* reference to controlling process */
668:
669: int sh_rerrcode; /* error code from M_ERROR */
670: int sh_werrcode; /* error code from M_ERROR */
671:
672: unsigned short sh_flags; /* miscellaneous flags */
673:
674: short sh_readopt; /* read options */
675: short sh_wropt; /* write options */
676:
677: unsigned short sh_wroff; /* write offset */
678:
679: sigpoll_t * sh_sigs; /* processes registered for SIGPOLL */
680:
681: toid_t sh_read_bufcall;/* ID for read bufcall () */
682:
683: shead_t * sh_linked; /* head of stream we are linked to */
684: muxid_t sh_muxid; /* our ID below that stream */
685:
686:
687: lock_t * sh_basic_lockp; /* */
688:
689: /*---- For process-level locking and timeout operations ----*/
690:
691: sv_t * sh_wait_sv; /* for process lock operations */
692:
693: int sh_lock_mask; /* which categories are locked */
694:
695: short sh_ref_count; /* references to stream memory */
696: short sh_open_count; /* successful open count */
697: short sh_attach_count;/* attachments to stream */
698: short sh_lock_count; /* processes queued or locked */
699: short sh_time_count; /* count of timeout checks */
700:
701: __clock_t sh_timeout_tick;/* current soonest timeout */
702: toid_t sh_timeout_id; /* ID of current active timeout */
703:
704: int sh_ioc_seq; /* ioctl () sequence number */
705: mblk_t * sh_ioc_msg; /* ioctl () messages */
706: };
707:
708:
709: /*
710: * A collection of functions for dealing with the stream head basic lock.
711: */
712:
713: #define SHEAD_LOCK(sheadp) LOCK ((sheadp)->sh_basic_lockp, plstr)
714: #define SHEAD_UNLOCK(sheadp,pl) UNLOCK ((sheadp)->sh_basic_lockp, pl)
715: #define SHEAD_ASSERT_LOCKED(sheadp) \
716: ASSERT ((sheadp) != NULL && \
717: TRYLOCK ((sheadp)->sh_basic_lockp, plstr) == invpl)
718:
719:
720: /*
721: * Masks for use with the "sh_flags" member.
722: */
723:
724: enum {
725: SH_READMSG = 0x0001, /* generate M_READ messages */
726: SH_NDELAY = 0x0002, /* non-STREAMS O_NDELAY semantics */
727: SH_TTY = 0x0004, /* stream is acting as a tty */
728: SH_TOSTOP = 0x0008, /* job control on background writes */
729:
730:
731: SH_HANGUP = 0x0010, /* stream has been hung up */
732:
733: SH_PLINK = 0x0020, /* stream is permanently linked */
734:
735: /*
736: * Permanent flags set when the stream is created. We do not need a
737: * flag to indicate a pipe, because pipes have a NULL "sh_tab" entry
738: * to mark them.
739: */
740:
741: SH_MASTER = 0x0100, /* master end of stream pipe */
742:
743:
744: /*
745: * This flag enables serialization of reads and writes. This is a
746: * local, experimental extension to STREAMS.
747: */
748:
749: SH_RWLOCKING = 0x0200
750: };
751:
752:
753: /*
754: * For stream pipes there is a master/slave relationship between the stream
755: * heads at each end. The following macros define some handy relationships
756: * between them to allow quick mapping from one to another.
757: */
758:
759: #define SHEAD_M2SLAVE(m) ((m) + 1)
760: #define SHEAD_SLAVE2M(s) ((s) - 1)
761: #define SHEAD_MASTER(sheadp) (((sheadp)->sh_flags & SH_MASTER) == 0 ? \
762: SHEAD_SLAVE2M (sheadp) : (sheadp))
763: #define SHEAD_OTHER(sheadp) (((sheadp)->sh_flags & SH_MASTER) == 0 ? \
764: SHEAD_SLAVE2M (sheadp) : \
765: SHEAD_M2SLAVE (sheadp))
766:
767: #define SHEAD_IS_PIPE(sheadp) ((sheadp)->sh_tab == NULL)
768:
769: #define SHEAD_HANGUP(sheadp) (((sheadp)->sh_flags & SH_HANGUP) != 0)
770:
771: #define SHEAD_READMSG(sheadp) (((sheadp)->sh_flags & SH_READMSG) != 0)
772:
773:
774: /*
775: * For working in with the abstract filesystem layer, we define a format for
776: * our opaque information.
777: */
778:
779: typedef struct {
780: shead_t * sheadp;
781: } scookie_t;
782:
783:
784:
785: __EXTERN_C_BEGIN__
786:
787: ssched_t * QSCHED_ALLOC __PROTO ((void));
788: void SSCHED_FREE __PROTO ((ssched_t * _sched));
789: int QSCHED_SCHEDULE __PROTO ((queue_t * _q, ssched_t * _sched));
790: void QSCHED_UNSCHEDULE
791: __PROTO ((queue_t * _q, ssched_t * _sched));
792: queue_t * QSCHED_GETFIRST __PROTO ((ssched_t * _sched));
793:
794: pl_t QFREEZE_TRACE __PROTO ((queue_t * _q,
795: __CONST__ char * _name));
796: void QFROZEN_TRACE __PROTO ((queue_t * _q,
797: __CONST__ char * _name));
798: void QUEUE_TRACE __PROTO ((queue_t * _q,
799: __CONST__ char * _name));
800: void QUNFREEZE_TRACE __PROTO ((queue_t * _q, pl_t _pl));
801:
802: void QUEUE_BACKENAB __PROTO ((queue_t * _q));
803: queue_t * QUEUE_NEXT __PROTO ((queue_t * _q));
804:
805: mblk_t * STRMEM_ALLOC __PROTO ((__size_t _size, int _pri,
806: int _flag));
807: void STRMEM_FREE __PROTO ((mblk_t * _bp, __size_t _size));
808:
809: mblk_t * MSGB_ALLOC __PROTO ((__size_t _size, int _pri,
810: int _flag));
811:
812: void SHEAD_WAKE __PROTO ((shead_t * _sheadp, cat_t _flag));
813: void SHEAD_SIGNAL __PROTO ((shead_t * _sheadp, uchar_t _sig));
814: int SHEAD_SRDOPT __PROTO ((shead_t * _sheadp, int _flag));
815: void QBAND_SETOPT __PROTO ((queue_t * _q,
816: struct stroptions * _so));
817:
818: qband_t * QUEUE_BAND __PROTO ((queue_t * _q, uchar_t _pri));
819: qband_t * QBAND_PREV __PROTO ((queue_t * _q, qband_t * _qbandp));
820:
821: void RUN_BUFCALLS __PROTO ((void));
822: void RUN_STREAMS __PROTO ((void));
823:
824: shead_t * SHEAD_FIND __PROTO ((n_dev_t _dev, slist_id_t _id));
825:
826: int STREAMS_OPEN __PROTO ((n_dev_t * _devp,
827: struct streamtab * _stabp,
828: int _mode, cred_t * _credp));
829: int STREAMS_CLOSE __PROTO ((shead_t * _sheadp, int _mode,
830: cred_t * _credp));
831:
832: int STREAMS_READ __PROTO ((shead_t * _sheadp, uio_t * _uiop));
833: int STREAMS_WRITE __PROTO ((shead_t * _sheadp, uio_t * _uiop));
834: int STREAMS_IOCTL __PROTO ((shead_t * _sheadp, int _cmd,
835: _VOID * _arg, int _mode,
836: cred_t * _credp, int * _rvalp));
837:
838: int STREAMS_CHPOLL __PROTO ((shead_t * _sheadp, short _events,
839: int _anyyet, short * _reventsp,
840: struct pollhead ** _phpp));
841:
842: int STREAMS_GETPMSG __PROTO ((shead_t * _sheadp,
843: struct strbuf * _ctlbuf,
844: struct strbuf * _databuf,
845: int * _bandp, int * _flagsp,
846: int _mode, int * _rvalp));
847: int STREAMS_PUTPMSG __PROTO ((shead_t * _sheadp,
848: struct strbuf * _ctlbuf,
849: struct strbuf * _databuf, int _band,
850: int _flags, int _mode,
851: int * _rvalp));
852:
853: __EXTERN_C_END__
854:
855:
856: /*
857: * This internal definition is the dual to QFREEZE_TRACE (), being the
858: * internal implementation of unfreezestr ().
859: */
860:
861: #define QUNFREEZE_TRACE(q,pl) SFREEZE_UNLOCK (q, pl)
862:
863:
864: /*
865: * Dealing with queue priority bands can be a little tricky; in particular,
866: * the definition of the linked-list structure of priority bands has some
867: * characteristics that may be unsuitable for some implementations.
868: * Specifically, the "qband" structure apparently is designed to function as
869: * a member of a singly-linked list rooted in the "queue" structure. This is
870: * flexible, but if there are several priority bands the time spent in
871: * dereferencing the link pointers might outweigh any extra cost involved in
872: * keeping the "band" structures in a vector [While the allocation cost is
873: * neglible in terms of time, there is a potentially high cost in terms of
874: * increasing the likelihood of a failure to allocate a band structure].
875: *
876: * The following internal functions have been defined to abstract away the
877: * details of how band structures are accessed from the queue, allowing a
878: * more time-efficient vector scheme to be used, or even a hybrid scheme
879: * where vectors are preferred but a linked-list fallback is available.
880: *
881: * The SVR4 DDI/DKI used to document the band structure, but that structure is
882: * no longer documented as of the SVR4 MP DDI/DKI.
883: */
884:
885: #define VECTOR_BANDS
886: #define VECTOR_BANDS_TEST /* test mode for VECTOR_BANDS */
887:
888: #ifdef VECTOR_BANDS
889:
890: #define QUEUE_BAND(q,pri) ((pri) > (q)->q_nband ? NULL : \
891: & (q)->q_bandp [pri - 1])
892:
893: #define QBAND_PREV(q,bandp) ((bandp) > (q)->q_bandp ? (bandp) - 1 : NULL)
894:
895: #endif /* defined (VECTOR_BANDS) */
896:
897:
898: #endif /* ! __KERNEL_STRMLIB_H__ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.