]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add per-thread instantiation for unlang
authorAlan T. DeKok <aland@freeradius.org>
Tue, 21 Sep 2021 13:06:43 +0000 (09:06 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 21 Sep 2021 13:17:53 +0000 (09:17 -0400)
and glue it into the various binaries

src/bin/unit_test_attribute.c
src/bin/unit_test_module.c
src/lib/io/worker.c
src/lib/unlang/base.c
src/lib/unlang/base.h
src/lib/unlang/compile.c
src/lib/unlang/compile.h
src/lib/unlang/unlang_priv.h

index 7e793d6cb46a177d1b44bc5f8423b10df1350452..b7d3ab448b558937abed0b3961fe328214dc114f 100644 (file)
@@ -3181,6 +3181,8 @@ int main(int argc, char *argv[])
                fr_perror("unit_test_attribute");
                EXIT_WITH_FAILURE;
        }
+       
+       unlang_thread_instantiate(autofree);
 
        if (!xlat_register(NULL, "test", xlat_test, false)) {
                ERROR("Failed registering xlat");
index 67f9faa0cc197d6cabda2b4f3f57d20ec10903c1..ee5a4d6d01077b6baccf59f113d17391259f4532 100644 (file)
@@ -728,6 +728,8 @@ int main(int argc, char *argv[])
                EXIT_WITH_FAILURE;
        }
 
+       unlang_thread_instantiate(autofree);
+
        /*
         *      Ensure that we load the correct virtual server for the
         *      protocol, if necessary.
index 9331395d9566d09f92de7686d13b1822ef2ae132..4039a0790ca143ac1ef03f60f0787cfd85f321e9 100644 (file)
@@ -57,6 +57,7 @@ RCSID("$Id$")
 #include <freeradius-devel/io/message.h>
 #include <freeradius-devel/io/time_tracking.h>
 #include <freeradius-devel/io/worker.h>
+#include <freeradius-devel/unlang/base.h>
 #include <freeradius-devel/unlang/call.h>
 #include <freeradius-devel/unlang/interpret.h>
 #include <freeradius-devel/util/dlist.h>
@@ -1214,6 +1215,8 @@ nomem:
 
        worker->name = talloc_strdup(worker, name); /* thread locality */
 
+       unlang_thread_instantiate(worker);
+
        if (config) worker->config = *config;
 
 #define CHECK_CONFIG(_x, _min, _max) do { \
index 5d3f2ea0d4a6b8a81ea717e5c46623740ddbeff1..2ddf0907db81f712386b799b2b9c2fad84d733c8 100644 (file)
@@ -86,6 +86,7 @@ int unlang_init_global(void)
        unlang_interpret_init_global();
 
        /* Register operations for the default keywords */
+       unlang_compile_init();
        unlang_condition_init();
        unlang_foreach_init();
        unlang_function_init();
@@ -111,6 +112,7 @@ void unlang_free_global(void)
 {
        if (--instance_count > 0) return;
 
+       unlang_compile_free();
        unlang_foreach_free();
        unlang_subrequest_op_free();
        xlat_free();
index 968c3e5d07e7eaeeff05c677f62d51881a74e6e1..9344383a32a67b5d8b2d3732a8eb1e162abae9b5 100644 (file)
@@ -40,6 +40,7 @@ int                   unlang_init_global(void);
 
 void                   unlang_free_global(void);
 
+int                    unlang_thread_instantiate(TALLOC_CTX *ctx) CC_HINT(nonnull);
 
 #ifdef __cplusplus
 }
index 77c7824a91719feaa9270bd01afaea94a03547f8..3ea331accbca5c748b95bedecec78a7a12b99e4b 100644 (file)
@@ -45,6 +45,17 @@ RCSID("$Id$")
 
 #define UNLANG_IGNORE ((unlang_t *) -1)
 
+static unsigned int unlang_number = 0;
+
+/*
+ *     For simplicity, this is just array[unlang_number].  Once we
+ *     call unlang_thread_instantiate(), the "unlang_number" above MUST
+ *     NOT change.
+ */
+static _Thread_local unlang_thread_t *unlang_thread_array;
+
+static fr_rb_tree_t *unlang_instruction_tree = NULL;
+
 /* Here's where we recognize all of our keywords: first the rcodes, then the
  * actions */
 fr_table_num_sorted_t const mod_rcode_table[] = {
@@ -3727,7 +3738,7 @@ static int unlang_pair_keywords_len = NUM_ELEMENTS(unlang_pair_keywords);
 
 
 /*
- *     Compile one entry of a module call.
+ *     Compile one unlang instruction
  */
 static unlang_t *compile_item(unlang_t *parent, unlang_compile_t *unlang_ctx, CONF_ITEM *ci)
 {
@@ -3740,13 +3751,22 @@ static unlang_t *compile_item(unlang_t *parent, unlang_compile_t *unlang_ctx, CO
        module_method_t         method;
        bool                    policy;
        unlang_op_compile_t     compile;
+       unlang_t                *c;
 
        if (cf_item_is_section(ci)) {
                cs = cf_item_to_section(ci);
                name = cf_section_name1(cs);
 
                compile = (unlang_op_compile_t) fr_table_value_by_str(unlang_section_keywords, name, NULL);
-               if (compile) return compile(parent, unlang_ctx, ci);
+               if (compile) {
+                       c = compile(parent, unlang_ctx, ci);
+               allocate_number:
+                       if (!c) return NULL;
+                       if (c == UNLANG_IGNORE) return UNLANG_IGNORE;
+
+                       c->number = unlang_number++;
+                       return c;
+               }
 
                /*
                 *      Forbid pair keywords as section names, e.g. "break { ... }"
@@ -3785,11 +3805,15 @@ static unlang_t *compile_item(unlang_t *parent, unlang_compile_t *unlang_ctx, CO
                 */
                if (((name[0] == '%') && ((name[1] == '{') || (name[1] == '('))) ||
                    (cf_pair_attr_quote(cp) == T_BACK_QUOTED_STRING)) {
-                       return compile_tmpl(parent, unlang_ctx, cp);
+                       c = compile_tmpl(parent, unlang_ctx, cp);
+                       goto allocate_number;
                }
 
                compile = (unlang_op_compile_t)fr_table_value_by_str(unlang_pair_keywords, name, NULL); /* Cast for -Wpedantic */
-               if (compile) return compile(parent, unlang_ctx, ci);
+               if (compile) {
+                       c = compile(parent, unlang_ctx, ci);
+                       goto allocate_number;
+               }
 
                /*
                 *      Forbid section keywords as pair names, e.g. bare "update"
@@ -3865,7 +3889,10 @@ check_for_module:
         *      named redundant / load-balance subsection defined in
         *      "instantiate".
         */
-       if (subcs) return compile_function(parent, unlang_ctx, ci, subcs, component, policy);
+       if (subcs) {
+               c = compile_function(parent, unlang_ctx, ci, subcs, component, policy);
+               goto allocate_number;
+       }
 
        /*
         *      Not a function.  It must be a real module.
@@ -3891,7 +3918,8 @@ check_for_module:
                                         &unlang_ctx2.section_name1, &unlang_ctx2.section_name2,
                                         realname);
        if (inst) {
-               return compile_module(parent, &unlang_ctx2, ci, inst, method, realname);
+               c = compile_module(parent, &unlang_ctx2, ci, inst, method, realname);
+               goto allocate_number;
        }
 
        /*
@@ -3934,7 +3962,8 @@ int unlang_compile(CONF_SECTION *cs, rlm_components_t component, tmpl_rules_t co
                                                .type = UNLANG_TYPE_GROUP,
                                                .len = sizeof(unlang_group_t),
                                                .type_name = "unlang_group_t",
-                                       };
+       };
+
        /*
         *      Don't compile it twice, and don't print out debug
         *      messages twice.
@@ -4000,3 +4029,68 @@ bool unlang_compile_is_keyword(const char *name)
 
        return (fr_table_value_by_str(unlang_pair_keywords, name, NULL) != NULL);
 }
+
+static int8_t instruction_cmp(void const *one, void const *two)
+{
+       unlang_t const *a = one;
+       unlang_t const *b = two;
+
+       return CMP(a->number, b->number);
+}
+
+
+void unlang_compile_init()
+{
+       unlang_instruction_tree = fr_rb_talloc_alloc(NULL, unlang_t, instruction_cmp, NULL);
+}
+
+void unlang_compile_free()
+{
+       TALLOC_FREE(unlang_instruction_tree);
+}
+
+
+/** Create thread-specific data structures for unlang
+ *
+ */
+int unlang_thread_instantiate(TALLOC_CTX *ctx)
+{
+       fr_rb_iter_inorder_t    iter;
+       unlang_t                *instruction;
+
+       if (unlang_thread_array) {
+               fr_strerror_const("already initialized");
+               return -1;
+       }
+
+       MEM(unlang_thread_array = talloc_zero_array(ctx, unlang_thread_t, unlang_number + 1));
+//     talloc_set_destructor(unlang_thread_array, _unlang_thread_array_free);
+
+       /*
+        *      Instantiate each instruction with thread-specific data.
+        */
+       for (instruction = fr_rb_iter_init_inorder(&iter, unlang_instruction_tree);
+            instruction;
+            instruction = fr_rb_iter_next_inorder(&iter)) {
+               unlang_op_t *op;
+
+               unlang_thread_array[instruction->number].instruction = instruction;
+
+               op = &unlang_ops[instruction->type];
+               if (!op->thread_instantiate) continue;
+
+               /*
+                *      Allocate any thread-specific instance data.
+                */
+               if (op->thread_inst_size) {
+                       MEM(unlang_thread_array[instruction->number].thread_inst = talloc_zero_array(unlang_thread_array, uint8_t, op->thread_inst_size));
+                       talloc_set_name_const(unlang_thread_array[instruction->number].thread_inst, op->thread_inst_type);
+               }
+
+               if (op->thread_instantiate(instruction, unlang_thread_array[instruction->number].thread_inst) < 0) {
+                       return -1;
+               }
+       }
+
+       return 0;
+}
index 1e7b579ee107b505832b6ad124c08d7637f341c6..e584f90311273379cb0f0b6231888260d17b4c56 100644 (file)
@@ -38,6 +38,10 @@ typedef struct {
        fr_retry_config_t       retry;
 } unlang_actions_t;
 
+void           unlang_compile_init(void);
+
+void           unlang_compile_free(void);
+
 int            unlang_compile(CONF_SECTION *cs, rlm_components_t component, tmpl_rules_t const *rules, void **instruction);
 
 bool           unlang_compile_is_keyword(const char *name);
index 00763f67e9a39634c36d39f80d79ce6829acc94e..85b62d86d721ad8d0be31ead615233cc7cb46c23 100644 (file)
@@ -122,6 +122,7 @@ struct unlang_s {
        char const              *debug_name;    //!< Printed in log messages when the node is executed.
        unlang_type_t           type;           //!< The specialisation of this node.
        bool                    closed;         //!< whether or not this section is closed to new statements
+       unsigned int            number;         //!< unique node number
        unlang_actions_t        actions;        //!< Priorities, etc. for the various return codes.
 };
 
@@ -192,6 +193,8 @@ typedef void (*unlang_signal_t)(request_t *request,
  */
 typedef void (*unlang_dump_t)(request_t *request, unlang_stack_frame_t *frame);
 
+typedef int (*unlang_thread_instantiate_t)(unlang_t const *instruction, void *thread_inst);
+
 /** An unlang operation
  *
  * These are like the opcodes in other interpreters.  Each operation, when executed
@@ -206,6 +209,11 @@ typedef struct {
 
        unlang_dump_t           dump;                           //!< Dump additional information about the frame state.
 
+       unlang_thread_instantiate_t thread_instantiate;         //!< per-thread instantiation function
+       size_t                  thread_inst_size;
+       char const              *thread_inst_type;
+
+
        bool                    debug_braces;                   //!< Whether the operation needs to print braces
                                                                ///< in debug mode.
 
@@ -218,6 +226,14 @@ typedef struct {
        size_t                  frame_state_pool_size;          //!< The total size of the pool to alloc.
 } unlang_op_t;
 
+typedef struct {
+       unlang_t const          *instruction;                   //!< instruction which we're executing
+       void                    *thread_inst;                   //!< thread-specific instance data
+       /*
+        *      And various other stats
+        */
+} unlang_thread_t;
+
 typedef struct {
        request_t               *request;
        int                     depth;                          //!< of this retry structure
@@ -504,6 +520,7 @@ int         unlang_interpret_push(request_t *request, unlang_t const *instruction,
 int            unlang_op_init(void);
 
 void           unlang_op_free(void);
+
 /** @} */
 
 /** @name io shims