Commit fe0d359e07f6ca8570fbff49f5d0b24c75c9af50

Thomas de Grivel 2024-12-10T09:45:19

fix cfn mutex and env_fork, add vegeta testing

diff --git a/.gitignore b/.gitignore
index 2c5b305..8436229 100644
--- a/.gitignore
+++ b/.gitignore
@@ -78,6 +78,7 @@ test/http/*.diff
 test/http/*.err
 test/http/*.out
 test/http/*.ret
+test/httpd/*.bin
 test/ikc3/.ikc3_history
 test/ikc3/.gdb_history
 test/ikc3/*.diff
diff --git a/libkc3/cfn.c b/libkc3/cfn.c
index 1587651..9556417 100644
--- a/libkc3/cfn.c
+++ b/libkc3/cfn.c
@@ -198,6 +198,24 @@ void cfn_delete (s_cfn *cfn)
   free(cfn);
 }
 
+bool cfn_eval (s_cfn *cfn)
+{
+  assert(cfn);
+  mutex_lock(&cfn->mutex);
+  if (! cfn->ready) {
+    if (! cfn_prep_cif(cfn))
+      goto ko;
+    if (! cfn_link(cfn))
+      goto ko;
+    cfn->ready = true;
+  }
+  mutex_unlock(&cfn->mutex);
+  return true;
+ ko:
+  mutex_unlock(&cfn->mutex);
+  return false;
+}
+
 s_cfn * cfn_init (s_cfn *cfn, const s_sym *name, s_list *arg_types,
                   const s_sym *result_type)
 {
@@ -269,6 +287,7 @@ s_cfn * cfn_init_copy (s_cfn *cfn, const s_cfn *src)
   tmp.ptr = src->ptr;
   tmp.macro = src->macro;
   tmp.special_operator = src->special_operator;
+  mutex_init(&tmp.mutex);
   *cfn = tmp;
   return cfn;
 }
@@ -282,6 +301,7 @@ s_cfn * cfn_link (s_cfn *cfn)
     err_write_1(": ");
     err_puts(dlerror());
     assert(! "cfn_link: dlsym failed");
+    mutex_unlock(&cfn->mutex);
     return NULL;
   }
   return cfn;
@@ -306,7 +326,10 @@ s_cfn * cfn_prep_cif (s_cfn *cfn)
   ffi_type *result_ffi_type;
   ffi_status status;
   assert(cfn);
-  mutex_lock(&cfn->mutex);
+  if (cfn->ready) {
+    result = cfn;
+    goto clean;
+  }
   if (! sym_to_ffi_type(cfn->result_type, NULL, &result_ffi_type))
     goto clean;
   if (cfn->arity) {
@@ -323,7 +346,8 @@ s_cfn * cfn_prep_cif (s_cfn *cfn)
         free(arg_ffi_type);
         goto clean;
       }
-      if (! sym_to_ffi_type(a->tag.data.sym, result_ffi_type, arg_ffi_type + i)) {
+      if (! sym_to_ffi_type(a->tag.data.sym, result_ffi_type,
+                            arg_ffi_type + i)) {
         free(arg_ffi_type);
         goto clean;
       }
@@ -353,9 +377,9 @@ s_cfn * cfn_prep_cif (s_cfn *cfn)
     assert(! "cfn_prep_cif: ffi_prep_cif: error");
     goto clean;
   }
+  cfn->ready = true;
   result = cfn;
  clean:
-  mutex_unlock(&cfn->mutex);
   return result;
 }
 
diff --git a/libkc3/cfn.h b/libkc3/cfn.h
index 7d537e2..2b40b60 100644
--- a/libkc3/cfn.h
+++ b/libkc3/cfn.h
@@ -27,11 +27,12 @@ s_cfn * cfn_init_copy (s_cfn *cfn, const s_cfn *src);
 void    cfn_delete (s_cfn *cfn);
 s_cfn * cfn_new_copy (const s_cfn *src);
 
-/* Observers */
+/* Observers. */
 s_tag * cfn_apply (s_cfn *cfn, s_list *args, s_tag *dest);
 s8      cfn_arity (const s_cfn *cfn);
 
-/* Modifiers */
+/* Operators. */
+bool    cfn_eval (s_cfn *cfn);
 s_cfn * cfn_link (s_cfn *cfn);
 s_cfn * cfn_prep_cif (s_cfn *cfn);
 
diff --git a/libkc3/env.c b/libkc3/env.c
index 810d9ca..c6005f6 100644
--- a/libkc3/env.c
+++ b/libkc3/env.c
@@ -908,13 +908,8 @@ bool env_eval_callable (s_env *env, s_callable *callable,
   case CALLABLE_CFN:
     if (! (tmp = callable_new_ref(callable)))
       return false;
-    if (! tmp->data.cfn.ready) {
-      if (! cfn_prep_cif(&tmp->data.cfn))
-        goto ko;
-      if (! cfn_link(&tmp->data.cfn))
-        goto ko;
-      tmp->data.cfn.ready = true;
-    }
+    if (! cfn_eval(&tmp->data.cfn))
+      return false;
     goto ok;
   case CALLABLE_FN:
     if (! (tmp = callable_new_copy(callable)))
diff --git a/test/httpd/Makefile b/test/httpd/Makefile
index 89a0655..554f008 100644
--- a/test/httpd/Makefile
+++ b/test/httpd/Makefile
@@ -19,4 +19,9 @@ debug: assets
 run: assets
 	${SRC_TOP}/httpd/.libs/kc3_httpd -C ${SRC_TOP}/test/httpd 127.0.0.1 15004
 
+VEGETA_RATE = 10
+
+vegeta:
+	vegeta attack -rate=${VEGETA_RATE} -duration=20s < vegeta-targets.txt | tee vegeta-result.rate\=${VEGETA_RATE}.bin | vegeta plot > vegeta-result.rate\=${VEGETA_RATE}.html
+
 .PHONY: assets asan cov debug main run
diff --git a/test/httpd/vegeta-targets.txt b/test/httpd/vegeta-targets.txt
new file mode 100644
index 0000000..f1f23a6
--- /dev/null
+++ b/test/httpd/vegeta-targets.txt
@@ -0,0 +1,9 @@
+GET http://127.0.0.1:15004/
+GET http://127.0.0.1:15004/test.txt
+GET http://127.0.0.1:15004/test.html
+GET http://127.0.0.1:15004/release
+GET http://127.0.0.1:15004/release/
+GET http://127.0.0.1:15004/doc
+GET http://127.0.0.1:15004/doc/
+GET http://127.0.0.1:15004/doc/1_KC3
+GET http://127.0.0.1:15004/doc/1_KC3/