|
|
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.