rmnet_core: Add generic module framework

Adds a simple, tracepoint inspired hook definiton framework to centralize
all calls to rmnet support modules. Modules can set and unset these hooks
freely, and modules may call one another's hooks without being forced to
link against any module other than the core rmnet module.

Change-Id: I949f7a17c95003e0c79262c6611b0602c7189e0c
Signed-off-by: Sean Tranchetti <quic_stranche@quicinc.com>
这个提交包含在:
Sean Tranchetti
2022-05-02 14:33:25 -07:00
父节点 8638373d04
当前提交 cf5990b0df
修改 5 个文件,包含 340 行新增0 行删除

100
core/rmnet_module.c 普通文件
查看文件

@@ -0,0 +1,100 @@
/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "rmnet_module.h"
struct rmnet_module_hook_info {
void *func __rcu;
};
static struct rmnet_module_hook_info
rmnet_module_hooks[__RMNET_MODULE_NUM_HOOKS];
void
rmnet_module_hook_register(const struct rmnet_module_hook_register_info *info,
int hook_count)
{
struct rmnet_module_hook_info *hook_info;
int i;
for (i = 0; i < hook_count; i++) {
int hook = info[i].hooknum;
if (hook < __RMNET_MODULE_NUM_HOOKS) {
hook_info = &rmnet_module_hooks[hook];
rcu_assign_pointer(hook_info->func, info[i].func);
}
}
}
EXPORT_SYMBOL(rmnet_module_hook_register);
bool rmnet_module_hook_is_set(int hook)
{
if (hook >= __RMNET_MODULE_NUM_HOOKS)
return false;
return rcu_dereference(rmnet_module_hooks[hook].func) != NULL;
}
EXPORT_SYMBOL(rmnet_module_hook_is_set);
void
rmnet_module_hook_unregister_no_sync(const struct rmnet_module_hook_register_info *info,
int hook_count)
{
struct rmnet_module_hook_info *hook_info;
int i;
for (i = 0; i < hook_count; i++) {
int hook = info[i].hooknum;
if (hook < __RMNET_MODULE_NUM_HOOKS) {
hook_info = &rmnet_module_hooks[hook];
rcu_assign_pointer(hook_info->func, NULL);
}
}
}
EXPORT_SYMBOL(rmnet_module_hook_unregister_no_sync);
#define __RMNET_HOOK_DEFINE(call, hook_num, proto, args, ret_type) \
int rmnet_module_hook_##call( \
__RMNET_HOOK_PROTO(RMNET_HOOK_PARAMS(proto), ret_type) \
) \
{ \
ret_type (*__func)(proto); \
struct rmnet_module_hook_info *__info = \
&rmnet_module_hooks[hook_num]; \
int __ret = 0; \
\
rcu_read_lock(); \
__func = rcu_dereference(__info->func); \
if (__func) { \
RMNET_HOOK_IF_NON_VOID_TYPE(ret_type)( ret_type __rc = ) \
__func(args); \
__ret = 1; \
\
RMNET_HOOK_IF_NON_VOID_TYPE(ret_type)( if (__ret_code) \
*__ret_code = __rc; )\
} \
\
rcu_read_unlock(); \
return __ret; \
} \
EXPORT_SYMBOL(rmnet_module_hook_##call);
#undef RMNET_MODULE_HOOK
#define RMNET_MODULE_HOOK(call, hook_num, proto, args, ret_type) \
__RMNET_HOOK_DEFINE(call, hook_num, RMNET_HOOK_PARAMS(proto), \
RMNET_HOOK_PARAMS(args), ret_type)
#define __RMNET_HOOK_MULTIREAD__
#include "rmnet_hook.h"