C Microkernel Realtime eXecutive
Realtime Operating System for Cortex-M based microcontrollers
Loading...
Searching...
No Matches
rpc.h
1
6
#pragma once
7
8
#include <arch/sysenter.h>
9
#include <stddef.h>
10
11
// Return 1 if type of x is pointer-to-something, 0 otherwise
12
#define __is_pointer(x) (__builtin_classify_type(x) == 5)
13
// Convert x to pointer to something if it is not already
14
#define __make_pointer_to(x) __builtin_choose_expr(!__is_pointer(x), &(x), (x))
15
// Dereference x if it is pointer. Do nothing if it is not.
16
#define __strip_pointer_from(x) *(__make_pointer_to(x))
17
18
/*
19
* Rearrange arguments to rpc_call syscall.
20
* We want to move RPC call arguments to occupy argument 1 .. 4 position.
21
* service and method goes next. The macro magic below deals with varying amount
22
* of arguments so that all calls to rpc_call() with less than 4 RPC arguments are
23
* padded to actual 4 arguments.
24
*/
25
26
#define CMRX_RPC_GET_ARG_COUNT_HELPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
27
#ifdef __clang__
28
# define CMRX_RPC_GET_ARG_COUNT(...) CMRX_RPC_GET_ARG_COUNT_HELPER(10, ## __VA_ARGS__ , 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
29
#else
30
# define CMRX_RPC_GET_ARG_COUNT(...) CMRX_RPC_GET_ARG_COUNT_HELPER(__VA_ARGS__ __VA_OPT__(,) 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
31
#endif
32
33
#define CMRX_RPC_PASTER(argcount) CMRX_RPC_CALL_ ## argcount
34
#define CMRX_RPC_EVALUATOR(argcount) CMRX_RPC_PASTER(argcount)
35
#define CMRX_RPC_CALL_4(si, mi, _0, _1, _2, _3) _rpc_call((unsigned long) _0, (unsigned long) _1, (unsigned long) _2, (unsigned long) _3, si, mi, 0xAA55AA55)
36
#define CMRX_RPC_CALL_3(si, mi, _0, _1, _2) _rpc_call((unsigned long) _0, (unsigned long) _1, (unsigned long) _2, 0, si, mi, 0xAA55AA55)
37
#define CMRX_RPC_CALL_2(si, mi, _0, _1) _rpc_call((unsigned long) _0, (unsigned long) _1, 0, 0, si, mi, 0xAA55AA55)
38
#define CMRX_RPC_CALL_1(si, mi, _0) _rpc_call((unsigned long) _0, 0, 0, 0, (void *) si, mi, 0xAA55AA55)
39
#define CMRX_RPC_CALL_0(si, mi) _rpc_call(0, 0, 0, 0, si, mi, 0xAA55AA55)
40
41
/*
42
* Perform compile time type checking of the RPC call arguments.
43
* This will emit code which apparently calls the rpc method directly. This call
44
* is never made in the runtime (and is optimized out as dead code anyway) but it will
45
* emit a fairly readable error if types of arguments to the RPC call don't match.
46
*/
47
48
#if defined __clang__
49
# define CMRX_RPC_TYPE_CHECKER(argcount, object, ...) if (0) { object((void *) 0 , ##__VA_ARGS__); }
50
#else
51
# define CMRX_RPC_TYPE_CHECKER(argcount, object, ...) if (0) { object((void *) 0 __VA_OPT__(,) __VA_ARGS__); }
52
#endif
53
54
#define CMRX_RPC_CHECK_TYPE_4(object, _0, _1, _2, _3) CMRX_RPC_CHECK_TYPE(object, (_0, _1, _2, _3))
55
#define CMRX_RPC_CHECK_TYPE_3(object, _0, _1, _2) CMRX_RPC_CHECK_TYPE(object, (_0, _1, _2))
56
#define CMRX_RPC_CHECK_TYPE_2(object, _0, _1) CMRX_RPC_CHECK_TYPE(object, (_0, _1))
57
#define CMRX_RPC_CHECK_TYPE_1(object, _0) CMRX_RPC_CHECK_TYPE(object, (_0))
58
#define CMRX_RPC_CHECK_TYPE_0(object, foo) CMRX_RPC_CHECK_TYPE(object, ())
59
60
#define CMRX_RPC_CHECK_TYPE(object, args) if (0) { object ## args }
61
62
/*
63
* Checker to make sure that the service instance is being called by pointer.
64
*/
65
66
#define CMRX_RPC_SERVICE_FORM_CHECKER_IMPL(object) "Service `" #object "` must be of a pointer to structure type!"
67
#define CMRX_RPC_SERVICE_FORM_CHECKER_AUX(object) CMRX_RPC_SERVICE_FORM_CHECKER_IMPL(object)
68
#define CMRX_RPC_SERVICE_FORM_CHECKER(object) _Static_assert(__builtin_classify_type(object) == 5, CMRX_RPC_SERVICE_FORM_CHECKER_AUX(object))
69
70
/*
71
* Checker to make sure that the layout of type being used to perform calls is correct.
72
* The CMRX ABI requires, that the `vtable` member is the first member in the struct.
73
* Otherwise kernel won't be able to locate the virtual method table during rpc_call()
74
* execution.
75
*/
76
77
#define CMRX_RPC_INTERFACE_CHECKER_IMPL(service_instance) "Service `" #service_instance "` has invalid layout! VTable must be the first member!"
78
#define CMRX_RPC_INTERFACE_CHECKER_AUX(service_instance) CMRX_RPC_INTERFACE_CHECKER_IMPL(service_instance)
79
#define CMRX_RPC_INTERFACE_CHECKER(service_instance) _Static_assert(offsetof(typeof(*(service_instance)), vtable) == 0, CMRX_RPC_INTERFACE_CHECKER_AUX(service_instance))
80
81
/*
82
* The master RPC call macro.
83
* This macro will emit several checks:
84
* - check that RPC service instance is a pointer to something.
85
* - check that va_args are actually compatible to what RPC method expects.
86
* - check the layout of RPC service (especially the position of the VTable)
87
* If all the checks will pass then RPC call is emitted. Note that all
88
* the checking is performed in the compile time.
89
*/
90
91
#define CMRX_RPC_CALL(service_instance, method_name, ...) \
92
CMRX_RPC_EVALUATOR(CMRX_RPC_GET_ARG_COUNT(__VA_ARGS__))(\
93
(service_instance), \
94
offsetof(typeof(*((service_instance)->vtable)), method_name) / sizeof(void *), \
95
##__VA_ARGS__); \
96
CMRX_RPC_SERVICE_FORM_CHECKER(service_instance); \
97
CMRX_RPC_TYPE_CHECKER(CMRX_RPC_GET_ARG_COUNT(__VA_ARGS__), (service_instance)->vtable->method_name, ##__VA_ARGS__) \
98
CMRX_RPC_INTERFACE_CHECKER(service_instance); \
99
114
#define interface_cast(type, service) _Generic(((service)->vtable), typeof((*((type*) 0))->vtable) : (type) service, default: service)
115
130
#ifdef __clang__
131
#define rpc_call(service_instance, method_name, ...) CMRX_RPC_CALL(service_instance, method_name, ##__VA_ARGS__)
132
#else
133
#define rpc_call(service_instance, method_name, ...) CMRX_RPC_CALL(service_instance, method_name __VA_OPT__(,) __VA_ARGS__)
134
#endif
152
__SYSCALL
int
_rpc_call
(
unsigned
long
arg0,
unsigned
long
arg1,
unsigned
long
arg2,
unsigned
long
arg3,
void
* service,
unsigned
method,
unsigned
canary);
153
159
__SYSCALL
void
rpc_return
(
void
);
160
rpc_return
__SYSCALL void rpc_return(void)
The way how RPC returns.
_rpc_call
int _rpc_call(void)
__SYSCALL
#define __SYSCALL
Mark function as syscall entrypoint in userspace.
Definition
sysenter.h:14
include
cmrx
ipc
rpc.h
Generated by
1.9.8