Coherent4.2.10/include/kernel/bufcall.h
/* (-lgl
* Coherent 386 release 4.2
* Copyright (c) 1982, 1993 by Mark Williams Company.
* All rights reserved. May not be copied without permission.
* For copying permission and licensing info, write licensing@mwc.com
-lgl) */
#ifndef __KERNEL_BUFCALL_H__
#define __KERNEL_BUFCALL_H__
/*
* This header file contains a number of definitions that aim at working around
* the enormous problems generated by the existence of callback functions
* as implemented by bufcall(), i.e., without argument checking. See the
* definition of the str_event structure in <kernel/strmlib.h> for a more
* complete discussion of the possible lossage caused by this.
*/
#include <common/ccompat.h>
#include <common/xdebug.h>
#include <sys/stream.h>
/*
* The most appealing solution to this problem is to define a solution that
* works with inline functions to get full argument type checking, and then
* to define an intermediate level for C that simply deals with ensuring that
* the arguments are passed through the regular bufcall () mechanism without
* lossage.
*
* Because the only genuinely safe way of doing this is via the use of stdargs
* (which require that the function be declared that way, in ISO C it is
* distinctly unsafe to cast function pointers such that the argument
* definitions are different). Either an underlying implementation uses this
* form of function call or there must be a forwarding function written that
* does some form of similar hack to perform what is effectively an unsafe
* cast.
*
* To ease the job of declaring potential fully-type-safe versions of the
* forwarding function, we provide a template-style macro that users
* can try and use.
*/
/*
* If you are using this header with an AT&T STREAMS implementation, either
* you can directly call bufcall () (if the AT&T header is not in fact
* prototyped) or you can must bufcall () indirectly through a special
* function safe_bufcall (). If you are using the MWC-supplied STREAMS, then
* bufcall () has been implemented and prototyped such that it does not
* perform any type-checking of the callback or callback-argument arguments.
*
* If you are compiling with the AT&T implementation and have determined that
* it is safe to do so, either define __STDARG_BUFCALL__ below or define it
* in the compiler command line.
*/
/* #define __STDARG_BUFCALL__ */
/*
* safe_bufcall () does a bufcall () but effectively overrides any declared
* prototype for bufcall (). In certain cases the underlying bufcall ()
* works this way.
*/
#ifdef __STDARG_BUFCALL__
# define safe_bufcall(s,p,f,a) bufcall (s, p, f, a)
# define safe_esbbcall(p,f,a) esbbcall (p, f, a)
#else
__EXTERN_C_BEGIN__
toid_t safe_bufcall __PROTO ((uint_t _size, int _pri, ...));
toid_t safe_esbbcall __PROTO ((int _pri, ...));
__EXTERN_C_END__
#endif
/*
* Clients should follow the general form here for declaring wrappers for
* callbacks that are private to clients (in general, the following types
* of callbacks are the only ones that would be visible at anything greater
* than file scope).
*/
#if __USE_INLINE__ && __USE_PROTO__
# define __INLINE_BUFCALL(name,type)\
__LOCAL__ __INLINE__ toid_t __CONCAT (bufcall_, name) \
(uint_t _size, int _pri, void (* _func) (type), type _arg) { \
return safe_bufcall (_size, _pri, _func, _arg); \
}
# define __INLINE_ESBBCALL(name,type)\
__LOCAL__ __INLINE__ toid_t __CONCAT (esbbcall_ ,name) \
(int _pri, void (* _func) (type), type _arg) { \
return safe_esbbcall (_pri, _func, arg); \
}
__LOCAL__ __INLINE__
toid_t bufcall_void (uint_t _size, int _pri, void (* _func) (void)) {
return safe_bufcall (_size, _pri, _func, 0);
}
__INLINE_BUFCALL (int, int);
__INLINE_BUFCALL (long, long);
__INLINE_BUFCALL (queue, queue_t *);
__LOCAL__ __INLINE__
toid_t esbbcall_void (int _pri, void (* _func) (void)) {
return safe_esbbcall (_pri, _func, 0);
}
__INLINE_ESBBCALL (int, int);
__INLINE_ESBBCALL (long, long);
__INLINE_ESBBCALL (queue, queue_t *);
#else /* if ! __USE_INLINE__ || ! __PROTO__ */
# define bufcall_void(s,p,f) safe_bufcall (s, p, f, 0)
# define bufcall_int(s,p,f,a) safe_bufcall (s, p, f,\
(int) (a))
# define bufcall_long(s,p,f,a) safe_bufcall (s, p, f,\
(long) (a))
# define bufcall_queue(s,p,f,a) safe_bufcall (s, p, f,\
(queue_t *) (a))
# define esbbcall_void(p,f) safe_esbbcall (p, f, 0)
# define esbbcall_int(p,f,a) safe_esbbcall (p, f, (int) (a))
# define esbbcall_long(p,f,a) safe_esbbcall (p, f, (long) (a))
# define esbbcall_queue(p,f,a) safe_esbbcall (p, f, (queue_t *) (a))
#endif /* ! __USE_INLINE__ || ! __PROTO__ */
#endif /* ! defined (__KERNEL_BUFCALL_H__) */