syscalls: greatly simplify system call declaration
To define a system call, it's now sufficient to simply tag the inline prototype with "__syscall" or "__syscall_inline" and include a special generated header at the end of the header file. The system call dispatch table and enumeration of system call IDs is now automatically generated. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
3d4f213a9c
commit
fa94ee7460
10 changed files with 291 additions and 65 deletions
25
Makefile
25
Makefile
|
@ -1023,7 +1023,28 @@ include/generated/syscall_macros.h: $(GEN_SYSCALL_HEADER)
|
||||||
$(Q)mkdir -p $(dir $@)
|
$(Q)mkdir -p $(dir $@)
|
||||||
$(Q)$(GEN_SYSCALL_HEADER) > $@
|
$(Q)$(GEN_SYSCALL_HEADER) > $@
|
||||||
|
|
||||||
syscall_macros: include/generated/syscall_macros.h
|
GEN_SYSCALLS := $(srctree)/scripts/gen_syscalls.py
|
||||||
|
|
||||||
|
define filechk_syscall_list.h
|
||||||
|
$(GEN_SYSCALLS) \
|
||||||
|
--include $(ZEPHYR_BASE)/include \
|
||||||
|
--base-output include/generated/syscalls \
|
||||||
|
--syscall-dispatch include/generated/dispatch.c.tmp
|
||||||
|
endef
|
||||||
|
|
||||||
|
include/generated/syscall_list.h: include/config/auto.conf FORCE
|
||||||
|
$(call filechk,syscall_list.h)
|
||||||
|
|
||||||
|
define filechk_syscall_dispatch.c
|
||||||
|
cat include/generated/dispatch.c.tmp
|
||||||
|
endef
|
||||||
|
|
||||||
|
include/generated/syscall_dispatch.c: include/generated/syscall_list.h FORCE
|
||||||
|
$(call filechk,syscall_dispatch.c)
|
||||||
|
|
||||||
|
syscall_generated: include/generated/syscall_macros.h \
|
||||||
|
include/generated/syscall_dispatch.c \
|
||||||
|
include/generated/syscall_list.h
|
||||||
|
|
||||||
define filechk_.config-sanitycheck
|
define filechk_.config-sanitycheck
|
||||||
(cat .config; \
|
(cat .config; \
|
||||||
|
@ -1093,7 +1114,7 @@ archprepare = $(strip \
|
||||||
)
|
)
|
||||||
|
|
||||||
# All the preparing..
|
# All the preparing..
|
||||||
prepare: $(archprepare) dts syscall_macros FORCE
|
prepare: $(archprepare) dts syscall_generated FORCE
|
||||||
$(Q)$(MAKE) $(build)=.
|
$(Q)$(MAKE) $(build)=.
|
||||||
|
|
||||||
# Generate some files
|
# Generate some files
|
||||||
|
|
|
@ -281,7 +281,9 @@ PREDEFINED = "CONFIG_SYS_CLOCK_EXISTS=y" \
|
||||||
"CONFIG_BT_BREDR=y" \
|
"CONFIG_BT_BREDR=y" \
|
||||||
"__deprecated=" \
|
"__deprecated=" \
|
||||||
"__printf_like(x, y)=" \
|
"__printf_like(x, y)=" \
|
||||||
"__attribute(x)__="
|
"__attribute(x)__=" \
|
||||||
|
"__syscall=" \
|
||||||
|
"__syscall_inline="
|
||||||
EXPAND_AS_DEFINED =
|
EXPAND_AS_DEFINED =
|
||||||
SKIP_FUNCTION_MACROS = NO
|
SKIP_FUNCTION_MACROS = NO
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
|
@ -2477,14 +2477,10 @@ struct k_sem {
|
||||||
*
|
*
|
||||||
* @return N/A
|
* @return N/A
|
||||||
*/
|
*/
|
||||||
static inline void k_sem_init(struct k_sem *sem, unsigned int initial_count,
|
__syscall static inline void k_sem_init(struct k_sem *sem,
|
||||||
|
unsigned int initial_count,
|
||||||
unsigned int limit);
|
unsigned int limit);
|
||||||
|
|
||||||
K_SYSCALL_DECLARE3_VOID(K_SYSCALL_SEM_INIT, k_sem_init,
|
|
||||||
struct k_sem *, sem,
|
|
||||||
unsigned int, initial_count,
|
|
||||||
unsigned int, limit);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Take a semaphore.
|
* @brief Take a semaphore.
|
||||||
*
|
*
|
||||||
|
@ -2506,11 +2502,7 @@ K_SYSCALL_DECLARE3_VOID(K_SYSCALL_SEM_INIT, k_sem_init,
|
||||||
* @retval -EBUSY Returned without waiting.
|
* @retval -EBUSY Returned without waiting.
|
||||||
* @retval -EAGAIN Waiting period timed out.
|
* @retval -EAGAIN Waiting period timed out.
|
||||||
*/
|
*/
|
||||||
static inline int k_sem_take(struct k_sem *sem, s32_t timeout);
|
__syscall static inline int k_sem_take(struct k_sem *sem, s32_t timeout);
|
||||||
|
|
||||||
K_SYSCALL_DECLARE2(K_SYSCALL_SEM_TAKE, k_sem_take, int,
|
|
||||||
struct k_sem *, sem,
|
|
||||||
s32_t, timeout);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Give a semaphore.
|
* @brief Give a semaphore.
|
||||||
|
@ -2524,10 +2516,7 @@ K_SYSCALL_DECLARE2(K_SYSCALL_SEM_TAKE, k_sem_take, int,
|
||||||
*
|
*
|
||||||
* @return N/A
|
* @return N/A
|
||||||
*/
|
*/
|
||||||
static inline void k_sem_give(struct k_sem *sem);
|
__syscall static inline void k_sem_give(struct k_sem *sem);
|
||||||
|
|
||||||
K_SYSCALL_DECLARE1_VOID(K_SYSCALL_SEM_GIVE, k_sem_give,
|
|
||||||
struct k_sem *, sem);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reset a semaphore's count to zero.
|
* @brief Reset a semaphore's count to zero.
|
||||||
|
@ -2538,16 +2527,13 @@ K_SYSCALL_DECLARE1_VOID(K_SYSCALL_SEM_GIVE, k_sem_give,
|
||||||
*
|
*
|
||||||
* @return N/A
|
* @return N/A
|
||||||
*/
|
*/
|
||||||
static inline void k_sem_reset(struct k_sem *sem);
|
__syscall_inline static inline void k_sem_reset(struct k_sem *sem);
|
||||||
|
|
||||||
static inline void _impl_k_sem_reset(struct k_sem *sem)
|
static inline void _impl_k_sem_reset(struct k_sem *sem)
|
||||||
{
|
{
|
||||||
sem->count = 0;
|
sem->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
K_SYSCALL_DECLARE1_VOID_INLINE(K_SYSCALL_SEM_RESET, k_sem_reset,
|
|
||||||
struct k_sem *, sem);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a semaphore's count.
|
* @brief Get a semaphore's count.
|
||||||
*
|
*
|
||||||
|
@ -2557,16 +2543,13 @@ K_SYSCALL_DECLARE1_VOID_INLINE(K_SYSCALL_SEM_RESET, k_sem_reset,
|
||||||
*
|
*
|
||||||
* @return Current semaphore count.
|
* @return Current semaphore count.
|
||||||
*/
|
*/
|
||||||
static inline unsigned int k_sem_count_get(struct k_sem *sem);
|
__syscall_inline static inline unsigned int k_sem_count_get(struct k_sem *sem);
|
||||||
|
|
||||||
static inline unsigned int _impl_k_sem_count_get(struct k_sem *sem)
|
static inline unsigned int _impl_k_sem_count_get(struct k_sem *sem)
|
||||||
{
|
{
|
||||||
return sem->count;
|
return sem->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
K_SYSCALL_DECLARE1_INLINE(K_SYSCALL_SEM_COUNT_GET, k_sem_count_get,
|
|
||||||
unsigned int, struct k_sem *, sem);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Statically define and initialize a semaphore.
|
* @brief Statically define and initialize a semaphore.
|
||||||
*
|
*
|
||||||
|
@ -4142,6 +4125,8 @@ inline void *operator new[](size_t size, void *ptr)
|
||||||
|
|
||||||
#endif /* defined(CONFIG_CPLUSPLUS) && defined(__cplusplus) */
|
#endif /* defined(CONFIG_CPLUSPLUS) && defined(__cplusplus) */
|
||||||
|
|
||||||
|
#include <syscalls/kernel.h>
|
||||||
|
|
||||||
#endif /* !_ASMLANGUAGE */
|
#endif /* !_ASMLANGUAGE */
|
||||||
|
|
||||||
#endif /* _kernel__h_ */
|
#endif /* _kernel__h_ */
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2017, Intel Corporation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache 2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _ZEPHYR_SYSCALL_LIST_H_
|
|
||||||
#define _ZEPHYR_SYSCALL_LIST_H_
|
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE
|
|
||||||
|
|
||||||
enum {
|
|
||||||
K_SYSCALL_BAD,
|
|
||||||
K_SYSCALL_SEM_INIT,
|
|
||||||
K_SYSCALL_SEM_GIVE,
|
|
||||||
K_SYSCALL_SEM_TAKE,
|
|
||||||
K_SYSCALL_SEM_RESET,
|
|
||||||
K_SYSCALL_SEM_COUNT_GET,
|
|
||||||
|
|
||||||
K_SYSCALL_LIMIT /* Always last */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _ASMLANGUAGE */
|
|
||||||
|
|
||||||
#endif /* _ZEPHYR_SYSCALL_LIST_H_ */
|
|
|
@ -95,6 +95,10 @@ do { \
|
||||||
#define __deprecated __attribute__((deprecated))
|
#define __deprecated __attribute__((deprecated))
|
||||||
#define ARG_UNUSED(x) (void)(x)
|
#define ARG_UNUSED(x) (void)(x)
|
||||||
|
|
||||||
|
/* Only used by gen_syscalls.py */
|
||||||
|
#define __syscall
|
||||||
|
#define __syscall_inline
|
||||||
|
|
||||||
#define likely(x) __builtin_expect((long)!!(x), 1L)
|
#define likely(x) __builtin_expect((long)!!(x), 1L)
|
||||||
#define unlikely(x) __builtin_expect((long)!!(x), 0L)
|
#define unlikely(x) __builtin_expect((long)!!(x), 0L)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#ifndef _kernel_offsets__h_
|
#ifndef _kernel_offsets__h_
|
||||||
#define _kernel_offsets__h_
|
#define _kernel_offsets__h_
|
||||||
|
|
||||||
|
#include <syscall_list.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The final link step uses the symbol _OffsetAbsSyms to force the linkage of
|
* The final link step uses the symbol _OffsetAbsSyms to force the linkage of
|
||||||
* offsets.o into the ELF image.
|
* offsets.o into the ELF image.
|
||||||
|
|
|
@ -190,12 +190,13 @@ static u32_t _handler_bad_syscall(u32_t bad_id, u32_t arg2, u32_t arg3,
|
||||||
CODE_UNREACHABLE;
|
CODE_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT] = {
|
static u32_t _handler_no_syscall(u32_t arg1, u32_t arg2, u32_t arg3,
|
||||||
[K_SYSCALL_BAD] = _handler_bad_syscall,
|
u32_t arg4, u32_t arg5, u32_t arg6, void *ssf)
|
||||||
|
{
|
||||||
|
printk("Unimplemented system call\n");
|
||||||
|
_arch_syscall_oops(ssf);
|
||||||
|
CODE_UNREACHABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <syscall_dispatch.c>
|
||||||
|
|
||||||
[K_SYSCALL_SEM_INIT] = _handler_k_sem_init,
|
|
||||||
[K_SYSCALL_SEM_GIVE] = _handler_k_sem_give,
|
|
||||||
[K_SYSCALL_SEM_TAKE] = _handler_k_sem_take,
|
|
||||||
[K_SYSCALL_SEM_RESET] = _handler_k_sem_reset,
|
|
||||||
[K_SYSCALL_SEM_COUNT_GET] = _handler_k_sem_count_get,
|
|
||||||
};
|
|
||||||
|
|
|
@ -356,7 +356,9 @@ our $Attribute = qr{
|
||||||
____cacheline_aligned|
|
____cacheline_aligned|
|
||||||
____cacheline_aligned_in_smp|
|
____cacheline_aligned_in_smp|
|
||||||
____cacheline_internodealigned_in_smp|
|
____cacheline_internodealigned_in_smp|
|
||||||
__weak
|
__weak|
|
||||||
|
__syscall|
|
||||||
|
__syscall_inline
|
||||||
}x;
|
}x;
|
||||||
our $Modifier;
|
our $Modifier;
|
||||||
our $Inline = qr{inline|__always_inline|noinline|__inline|__inline__};
|
our $Inline = qr{inline|__always_inline|noinline|__inline|__inline__};
|
||||||
|
|
|
@ -56,9 +56,6 @@ def gen_defines_inner(ret, argc, kernel_only=False, user_only=False):
|
||||||
gen_macro(ret, argc, inline=True)
|
gen_macro(ret, argc, inline=True)
|
||||||
newline()
|
newline()
|
||||||
|
|
||||||
if not user_only:
|
|
||||||
sys.stdout.write("\textern u32_t _handler_##name(u32_t, u32_t, u32_t, u32_t, u32_t, u32_t, void *); \\\n")
|
|
||||||
|
|
||||||
gen_fn(ret, argc, "name");
|
gen_fn(ret, argc, "name");
|
||||||
newline()
|
newline()
|
||||||
sys.stdout.write("\t{")
|
sys.stdout.write("\t{")
|
||||||
|
|
238
scripts/gen_syscalls.py
Executable file
238
scripts/gen_syscalls.py
Executable file
|
@ -0,0 +1,238 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# Copyright (c) 2017 Intel Corporation
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
api_regex = re.compile(r'''
|
||||||
|
__(syscall|syscall_inline)\s+ # __syscall or __syscall_inline
|
||||||
|
static\s+inline\s+ # All prototypes are static inline functions
|
||||||
|
([^(]+) # type and name of system call (split later)
|
||||||
|
[(] # Function opening parenthesis
|
||||||
|
([^)]*) # Arg list (split later)
|
||||||
|
[)] # Closing parenthesis
|
||||||
|
''', re.MULTILINE | re.VERBOSE)
|
||||||
|
|
||||||
|
typename_regex = re.compile(r'(.*?)([A-Za-z0-9_]+)$')
|
||||||
|
|
||||||
|
class SyscallParseException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def typename_split(item):
|
||||||
|
if "[" in item:
|
||||||
|
raise SyscallParseException("Please pass arrays to syscalls as pointers, unable to process '%s'"
|
||||||
|
% item)
|
||||||
|
|
||||||
|
if "(" in item:
|
||||||
|
raise SyscallParseException("Please use typedefs for function pointers")
|
||||||
|
|
||||||
|
m = typename_regex.match(item).groups()
|
||||||
|
return (m[0].strip(), m[1])
|
||||||
|
|
||||||
|
|
||||||
|
def analyze_fn(match_group, fn):
|
||||||
|
variant, func, args = match_group
|
||||||
|
|
||||||
|
try:
|
||||||
|
if args == "void":
|
||||||
|
args = []
|
||||||
|
else:
|
||||||
|
args = [typename_split(a.strip()) for a in args.split(",")]
|
||||||
|
|
||||||
|
func_type, func_name = typename_split(func)
|
||||||
|
except SyscallParseException:
|
||||||
|
sys.stderr.write("In declaration of %s\n" % func)
|
||||||
|
raise
|
||||||
|
|
||||||
|
sys_id = "K_SYSCALL_" + func_name.upper()
|
||||||
|
is_void = (func_type == "void")
|
||||||
|
|
||||||
|
# Get the proper system call macro invocation, which depends on the
|
||||||
|
# number of arguments, the return type, and whether the implementation
|
||||||
|
# is an inline function
|
||||||
|
macro = "K_SYSCALL_DECLARE%d%s%s" % (len(args),
|
||||||
|
"_VOID" if is_void else "",
|
||||||
|
"_INLINE" if variant == "syscall_inline" else "")
|
||||||
|
|
||||||
|
# Flatten the argument lists and generate a comma separated list
|
||||||
|
# of t0, p0, t1, p1, ... tN, pN as expected by the macros
|
||||||
|
flat_args = [i for sublist in args for i in sublist]
|
||||||
|
if not is_void:
|
||||||
|
flat_args = [func_type] + flat_args
|
||||||
|
flat_args = [sys_id, func_name] + flat_args
|
||||||
|
argslist = ", ".join(flat_args)
|
||||||
|
|
||||||
|
invocation = "%s(%s);" % (macro, argslist)
|
||||||
|
|
||||||
|
handler = "_handler_" + func_name
|
||||||
|
|
||||||
|
# Entry in _k_syscall_table
|
||||||
|
table_entry = "[%s] = %s" % (sys_id, handler)
|
||||||
|
|
||||||
|
return (fn, handler, invocation, sys_id, table_entry)
|
||||||
|
|
||||||
|
|
||||||
|
def analyze_headers(base_path):
|
||||||
|
ret = []
|
||||||
|
|
||||||
|
for root, dirs, files in os.walk(base_path):
|
||||||
|
for fn in files:
|
||||||
|
if not fn.endswith(".h"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
with open(os.path.join(root, fn)) as fp:
|
||||||
|
try:
|
||||||
|
result = [analyze_fn(mo.groups(), fn)
|
||||||
|
for mo in api_regex.finditer(fp.read())]
|
||||||
|
except Exception:
|
||||||
|
sys.stderr.write("While parsing %s\n" % fn)
|
||||||
|
raise
|
||||||
|
|
||||||
|
ret.extend(result)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
table_template = """/* auto-generated by gen_syscalls.py, don't edit */
|
||||||
|
|
||||||
|
/* Weak handler functions that get replaced by the real ones unles a system
|
||||||
|
* call is not implemented due to kernel configuration
|
||||||
|
*/
|
||||||
|
%s
|
||||||
|
|
||||||
|
const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT] = {
|
||||||
|
\t%s
|
||||||
|
};
|
||||||
|
"""
|
||||||
|
|
||||||
|
list_template = """
|
||||||
|
/* auto-generated by gen_syscalls.py, don't edit */
|
||||||
|
#ifndef _ZEPHYR_SYSCALL_LIST_H_
|
||||||
|
#define _ZEPHYR_SYSCALL_LIST_H_
|
||||||
|
|
||||||
|
#ifndef _ASMLANGUAGE
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
\t%s
|
||||||
|
};
|
||||||
|
|
||||||
|
%s
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _ASMLANGUAGE */
|
||||||
|
|
||||||
|
#endif /* _ZEPHYR_SYSCALL_LIST_H_ */
|
||||||
|
"""
|
||||||
|
|
||||||
|
syscall_template = """
|
||||||
|
/* auto-generated by gen_syscalls.py, don't edit */
|
||||||
|
|
||||||
|
#ifndef _ASMLANGUAGE
|
||||||
|
|
||||||
|
#include <syscall_list.h>
|
||||||
|
#include <syscall_macros.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%s
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
"""
|
||||||
|
|
||||||
|
handler_template = """
|
||||||
|
extern u32_t %s(u32_t arg1, u32_t arg2, u32_t arg3,
|
||||||
|
u32_t arg4, u32_t arg5, u32_t arg6, void *ssf);
|
||||||
|
"""
|
||||||
|
|
||||||
|
weak_template = """
|
||||||
|
__weak ALIAS_OF(_handler_no_syscall)
|
||||||
|
u32_t %s(u32_t arg1, u32_t arg2, u32_t arg3,
|
||||||
|
u32_t arg4, u32_t arg5, u32_t arg6, void *ssf);
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
global args
|
||||||
|
parser = argparse.ArgumentParser(description = __doc__,
|
||||||
|
formatter_class = argparse.RawDescriptionHelpFormatter)
|
||||||
|
|
||||||
|
parser.add_argument("-i", "--include", required=True,
|
||||||
|
help="Base include directory")
|
||||||
|
parser.add_argument("-d", "--syscall-dispatch", required=True,
|
||||||
|
help="output C system call dispatch table file")
|
||||||
|
parser.add_argument("-o", "--base-output", required=True,
|
||||||
|
help="Base output directory for syscall macro headers")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parse_args()
|
||||||
|
|
||||||
|
syscalls = analyze_headers(args.include)
|
||||||
|
invocations = {}
|
||||||
|
ids = []
|
||||||
|
table_entries = []
|
||||||
|
handlers = []
|
||||||
|
|
||||||
|
for fn, handler, inv, sys_id, entry in syscalls:
|
||||||
|
if fn not in invocations:
|
||||||
|
invocations[fn] = []
|
||||||
|
|
||||||
|
invocations[fn].append(inv)
|
||||||
|
ids.append(sys_id)
|
||||||
|
table_entries.append(entry)
|
||||||
|
handlers.append(handler)
|
||||||
|
|
||||||
|
with open(args.syscall_dispatch, "w") as fp:
|
||||||
|
table_entries.append("[K_SYSCALL_BAD] = _handler_bad_syscall")
|
||||||
|
|
||||||
|
weak_defines = "".join([weak_template % name for name in handlers])
|
||||||
|
|
||||||
|
fp.write(table_template % (weak_defines, ",\n\t".join(table_entries)))
|
||||||
|
|
||||||
|
# Listing header emitted to stdout
|
||||||
|
ids.sort()
|
||||||
|
ids.extend(["K_SYSCALL_BAD", "K_SYSCALL_LIMIT"])
|
||||||
|
handler_defines = "".join([handler_template % name for name in handlers])
|
||||||
|
sys.stdout.write(list_template % (",\n\t".join(ids), handler_defines))
|
||||||
|
|
||||||
|
os.makedirs(args.base_output, exist_ok=True)
|
||||||
|
for fn, invo_list in invocations.items():
|
||||||
|
out_fn = os.path.join(args.base_output, fn)
|
||||||
|
|
||||||
|
header = syscall_template % "\n\n".join(invo_list)
|
||||||
|
|
||||||
|
# Check if the file already exists, and if there are no changes,
|
||||||
|
# don't touch it since that will force an incremental rebuild
|
||||||
|
if os.path.exists(out_fn):
|
||||||
|
with open(out_fn, "r") as fp:
|
||||||
|
old_data = fp.read()
|
||||||
|
|
||||||
|
if old_data == header:
|
||||||
|
continue
|
||||||
|
|
||||||
|
with open(out_fn, "w") as fp:
|
||||||
|
fp.write(header)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue