|
|
1.1 root 1: #ifndef __KERNEL_BUFCALL_H__
2: #define __KERNEL_BUFCALL_H__
3:
4: /*
5: * This header file contains a number of definitions aimed at working around
6: * the enormous problems generated by the existence of callback functions
7: * as implemented by bufcall (), ie without argument checking. See the
8: * definition of the str_event structure in <sys/strmlib.h> for a more
9: * complete discussion of the possible lossage caused by this.
10: */
11:
12: /*
13: *-IMPORTS:
14: * <common/ccompat.h>
15: * __ANY_ARGS__
16: * __INLINE__
17: * __USE_INLINE__
18: * __PROTO ()
19: * <common/xdebug.h>
20: * __LOCAL__
21: * <sys/stream.h>
22: * queue_t
23: * toid_t
24: * uint_t
25: */
26:
27: #include <common/ccompat.h>
28: #include <common/xdebug.h>
29: #include <sys/stream.h>
30:
31:
32: /*
33: * The most appealing solution to this problem is to define a solution that
34: * works with inline functions to get full argument type checking, and then
35: * to define an intermediate level for C that simply deals with ensuring that
36: * the arguments are passed through the regular bufcall () mechanism without
37: * lossage.
38: *
39: * Since the only genuinely safe way of doing this is via the use of stdargs
40: * (which require that the function be declared that way, in ISO C it is
41: * distinctly unsafe to cast function pointers such that the argument
42: * definitions are different). Either an underlying implementation uses this
43: * form of function call or there must be a forwarding function written that
44: * does some form of similar hack to perform what is effectively an unsafe
45: * cast.
46: *
47: * In order to make the job of declaring potential fully-type-safe versions
48: * of the forwarding function, we provide a template-style macro that users
49: * can try and use.
50: */
51:
52: /*
53: * If you are using this header with an AT&T STREAMS implementation, either
54: * you can directly call bufcall () (if the AT&T header is not in fact
55: * prototyped) or you can must bufcall () indirectly through a special
56: * function safe_bufcall (). If you are using the MWC-supplied STREAMS, then
57: * bufcall () has been implemented and prototyped such that it does not
58: * perform any type-checking of the callback or callback-argument arguments.
59: *
60: * If you are compiling with the AT&T implementation and have determined that
61: * it is safe to do so, either define __STDARG_BUFCALL__ below or define it
62: * in the compiler command line.
63: */
64:
65: /* #define __STDARG_BUFCALL__ */
66:
67: /*
68: * safe_bufcall () does a bufcall () but effectively overrides any declared
69: * prototype for bufcall (). In certain cases the underlying bufcall ()
70: * works this way.
71: */
72:
73: #ifdef __STDARG_BUFCALL__
74:
75: # define safe_bufcall(s,p,f,a) bufcall (s, p, f, a)
76: # define safe_esbbcall(p,f,a) esbbcall (p, f, a)
77:
78: #else
79:
80: __EXTERN_C_BEGIN__
81:
82: toid_t safe_bufcall __PROTO ((uint_t _size, int _pri, ...));
83: toid_t safe_esbbcall __PROTO ((int _pri, ...));
84:
85: __EXTERN_C_END__
86:
87: #endif
88:
89:
90: /*
91: * Clients should follow the general form here for declaring wrappers for
92: * callbacks that are private to clients (in general, the following types
93: * of callbacks are the only ones that would be visible at anything greater
94: * than file scope).
95: */
96:
97:
98: #if __USE_INLINE__ && __USE_PROTO__
99:
100: # define __INLINE_BUFCALL(name,type)\
101: __LOCAL__ __INLINE__ toid_t __CONCAT (bufcall_, name) \
102: (uint_t _size, int _pri, void (* _func) (type), type _arg) { \
103: return safe_bufcall (_size, _pri, _func, _arg); \
104: }
105: # define __INLINE_ESBBCALL(name,type)\
106: __LOCAL__ __INLINE__ toid_t __CONCAT (esbbcall_ ,name) \
107: (int _pri, void (* _func) (type), type _arg) { \
108: return safe_esbbcall (_pri, _func, arg); \
109: }
110:
111: __LOCAL__ __INLINE__
112: toid_t bufcall_void (uint_t _size, int _pri, void (* _func) (void)) {
113: return safe_bufcall (_size, _pri, _func, 0);
114: }
115:
116: __INLINE_BUFCALL (int, int);
117: __INLINE_BUFCALL (long, long);
118: __INLINE_BUFCALL (queue, queue_t *);
119:
120: __LOCAL__ __INLINE__
121: toid_t esbbcall_void (int _pri, void (* _func) (void)) {
122: return safe_esbbcall (_pri, _func, 0);
123: }
124:
125: __INLINE_ESBBCALL (int, int);
126: __INLINE_ESBBCALL (long, long);
127: __INLINE_ESBBCALL (queue, queue_t *);
128:
129: #else /* if ! __USE_INLINE__ || ! __PROTO__ */
130:
131: # define bufcall_void(s,p,f) safe_bufcall (s, p, f, 0)
132: # define bufcall_int(s,p,f,a) safe_bufcall (s, p, f,\
133: (int) (a))
134: # define bufcall_long(s,p,f,a) safe_bufcall (s, p, f,\
135: (long) (a))
136: # define bufcall_queue(s,p,f,a) safe_bufcall (s, p, f,\
137: (queue_t *) (a))
138:
139: # define esbbcall_void(p,f) safe_esbbcall (p, f, 0)
140: # define esbbcall_int(p,f,a) safe_esbbcall (p, f, (int) (a))
141: # define esbbcall_long(p,f,a) safe_esbbcall (p, f, (long) (a))
142: # define esbbcall_queue(p,f,a) safe_esbbcall (p, f, (queue_t *) (a))
143:
144: #endif /* ! __USE_INLINE__ || ! __PROTO__ */
145:
146: #endif /* ! defined (__KERNEL_BUFCALL_H__) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.