diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-01-17 20:30:41 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-02-12 20:55:19 -0700 |
commit | 1793bda7f3e445c5ad81cf108589f8b1edcda4eb (patch) | |
tree | 41fe1255c206a6ce8f4b02aad58fe66fa4415b8e /lib9p/idl.gen | |
parent | e9de61146146b250dd1c6977086a62435c21d771 (diff) |
lib9p: idl.gen: Enforce a max WELEM for 9P2000.e
Diffstat (limited to 'lib9p/idl.gen')
-rwxr-xr-x | lib9p/idl.gen | 80 |
1 files changed, 68 insertions, 12 deletions
diff --git a/lib9p/idl.gen b/lib9p/idl.gen index ead9bc5..bf0935c 100755 --- a/lib9p/idl.gen +++ b/lib9p/idl.gen @@ -224,7 +224,9 @@ class BufferSize: exp_size: int # "expected" or max-reasonable size max_size: int # really just here to sanity-check against typ.max_size(version) max_copy: int + max_copy_extra: str max_iov: int + max_iov_extra: str _starts_with_copy: bool _ends_with_copy: bool @@ -233,7 +235,9 @@ class BufferSize: self.exp_size = 0 self.max_size = 0 self.max_copy = 0 + self.max_copy_extra = "" self.max_iov = 0 + self.max_iov_extra = "" self._starts_with_copy = False self._ends_with_copy = False @@ -271,17 +275,36 @@ def get_buffer_size(typ: idl.Type, version: str) -> BufferSize: sub = get_buffer_size(child.typ, version) ret.exp_size += sub.exp_size * 16 # HEURISTIC: MAXWELEM ret.max_size += sub.max_size * child.max_cnt - ret.max_copy += sub.max_copy * child.max_cnt - if sub.max_iov == 1 and sub._starts_with_copy: # is purely copy - ret.max_iov += 1 - else: # contains zero-copy segments - ret.max_iov += sub.max_iov * child.max_cnt - if ret._ends_with_copy and sub._starts_with_copy: - # we can merge this one + if child.name == "wname" and path.root.name in ( + "Tsread", + "Tswrite", + ): # SPECIAL (9P2000.e) + assert ret._ends_with_copy + assert sub._starts_with_copy + assert not sub._ends_with_copy + ret.max_copy_extra = ( + f" + (CONFIG_9P_MAX_9P2000_e_WELEM * {sub.max_copy})" + ) + ret.max_iov_extra = ( + f" + (CONFIG_9P_MAX_9P2000_e_WELEM * {sub.max_iov})" + ) ret.max_iov -= 1 - if sub._ends_with_copy and sub._starts_with_copy and sub.max_iov > 1: - # we can merge these - ret.max_iov -= child.max_cnt - 1 + else: + ret.max_copy += sub.max_copy * child.max_cnt + if sub.max_iov == 1 and sub._starts_with_copy: # is purely copy + ret.max_iov += 1 + else: # contains zero-copy segments + ret.max_iov += sub.max_iov * child.max_cnt + if ret._ends_with_copy and sub._starts_with_copy: + # we can merge this one + ret.max_iov -= 1 + if ( + sub._ends_with_copy + and sub._starts_with_copy + and sub.max_iov > 1 + ): + # we can merge these + ret.max_iov -= child.max_cnt - 1 ret._ends_with_copy = sub._ends_with_copy return WalkCmd.DONT_RECURSE elif not isinstance(child.typ, idl.Struct): @@ -332,6 +355,14 @@ def gen_h(versions: set[str], typs: list[idl.Type]) -> str: ret += "\n" ret += f"#ifndef {c_ver_ifdef({ver})}\n" ret += f"\t#error config.h must define {c_ver_ifdef({ver})}\n" + if ver == "9P2000.e": # SPECIAL (9P2000.e) + ret += "#else\n" + ret += f"\t#if {c_ver_ifdef({ver})}\n" + ret += "\t\t#ifndef(CONFIG_9P_MAX_9P2000_e_WELEM)\n" + ret += f"\t\t\t#error if {c_ver_ifdef({ver})} then config.h must define CONFIG_9P_MAX_9P2000_e_WELEM\n" + ret += "\t\t#endif\n" + ret += "\t\tstatic_assert(CONFIG_9P_MAX_9P2000_e_WELEM > 0);\n" + ret += "\t#endif\n" ret += "#endif\n" ret += f""" @@ -404,7 +435,7 @@ enum {idprefix}version {{ ret += f"min_size = {sz.min_size:,} ; exp_size = {sz.exp_size:,} ; max_size = {sz.max_size:,}" if sz.max_size > u32max: ret += " (warning: >UINT32_MAX)" - ret += f" ; max_iov = {sz.max_iov:,} ; max_copy = {sz.max_copy:,}" + ret += f" ; max_iov = {sz.max_iov:,}{sz.max_iov_extra} ; max_copy = {sz.max_copy:,}{sz.max_copy_extra}" return ret ret += per_version_comment(typ, sum_size) @@ -478,6 +509,9 @@ enum {idprefix}version {{ ret += """ /* sizes **********************************************************************/ """ + ret += "\n" + ret += f"#define _{idprefix.upper()}MAX(a, b) ((a) > (b)) ? (a) : (b)\n" + tmsg_max_iov: dict[str, int] = {} tmsg_max_copy: dict[str, int] = {} rmsg_max_iov: dict[str, int] = {} @@ -485,6 +519,8 @@ enum {idprefix}version {{ for typ in typs: if not isinstance(typ, idl.Message): continue + if typ.name in ("Tsread", "Tswrite"): # SPECIAL (9P2000.e) + continue max_iov = tmsg_max_iov if typ.msgid % 2 == 0 else rmsg_max_iov max_copy = tmsg_max_copy if typ.msgid % 2 == 0 else rmsg_max_copy for version in typ.in_versions: @@ -511,9 +547,29 @@ enum {idprefix}version {{ ret += "\n" directive = "if" + seen_e = False # SPECIAL (9P2000.e) for maxval in sorted(inv, reverse=True): ret += f"#{directive} {c_ver_ifdef(inv[maxval])}\n" - ret += f"\t#define {idprefix.upper()}{name.upper()} {maxval}\n" + indent = 1 + if name.startswith("tmsg") and not seen_e: # SPECIAL (9P2000.e) + typ = next(typ for typ in typs if typ.name == "Tswrite") + sz = get_buffer_size(typ, "9P2000.e") + match name: + case "tmsg_max_iov": + maxexpr = f"{sz.max_iov}{sz.max_iov_extra}" + case "tmsg_max_copy": + maxexpr = f"{sz.max_copy}{sz.max_copy_extra}" + case _: + assert False + ret += f"\t#if {c_ver_ifdef({"9P2000.e"})}\n" + ret += f"\t\t#define {idprefix.upper()}{name.upper()} _{idprefix.upper()}MAX({maxval}, {maxexpr})\n" + ret += f"\t#else\n" + indent += 1 + ret += f"{'\t'*indent}#define {idprefix.upper()}{name.upper()} {maxval}\n" + if name.startswith("tmsg") and not seen_e: # SPECIAL (9P2000.e) + ret += "\t#endif\n" + if "9P2000.e" in inv[maxval]: + seen_e = True directive = "elif" ret += "#endif\n" |