Commit 81bd6d5a4e5d41556d40914cdd1bb74e01b6157d

Authored by Alain Prouté
1 parent b9f7794f

New version 1.14: new form of 'delegate' taking priorities into account (see anu…

…bis_dev/manuals/en/Anubis-doc-1-13.pdf)
anubis_dev/compiler/src/compil.h
@@ -417,7 +417,9 @@ extern Expr linecol(void); @@ -417,7 +417,9 @@ extern Expr linecol(void);
417 item(wait_for)\ 417 item(wait_for)\
418 item(give_up)\ 418 item(give_up)\
419 item(delegate)\ 419 item(delegate)\
  420 + item(delegatep)\
420 item(start)\ 421 item(start)\
  422 + item(startp)\
421 item(finish)\ 423 item(finish)\
422 item(copy_stack_ptr)\ 424 item(copy_stack_ptr)\
423 item(copy_stack_mixed)\ 425 item(copy_stack_mixed)\
@@ -983,71 +985,7 @@ extern int max_tpair_load; @@ -983,71 +985,7 @@ extern int max_tpair_load;
983 #define cdr7(x) (cdr(cdr6(x))) 985 #define cdr7(x) (cdr(cdr6(x)))
984 986
985 extern Expr nthcdr(Expr n, Expr l); // get n-th cdr of l 987 extern Expr nthcdr(Expr n, Expr l); // get n-th cdr of l
986 -  
987 -#define term_switch(term,name)\  
988 - switch(car(term)) {\  
989 - case alt_number: goto alt_number_##name;\  
990 - case protect: goto protect_##name;\  
991 - case lock: goto lock_##name;\  
992 - case alert: goto alert_##name;\  
993 - case debug_avm: goto debug_avm_##name;\  
994 - case terminal: goto terminal_##name;\  
995 - case integer: goto integer_##name;\  
996 - case fpnum: goto fpnum_##name;\  
997 - case symbol: goto symbol_##name;\  
998 - case of_type: goto of_type_##name;\  
999 - case constructor: goto constructor_##name;\  
1000 - case lambda: goto lambda_##name;\  
1001 - case app: goto app_##name;\  
1002 - case cond: goto cond_##name;\  
1003 - case select_cond: goto select_cond_##name;\  
1004 - case with: goto with_##name;\  
1005 - case string: goto string_##name;\  
1006 - case anb_read: goto anb_read_##name;\  
1007 - case anb_write: goto anb_write_##name;\  
1008 - case wait_for: goto wait_for_##name;\  
1009 - case delegate: goto delegate_##name;\  
1010 - case set: goto set_##name;\  
1011 - case omega_true: goto omega_true_##name;\  
1012 - case omega_false: goto omega_false_##name;\  
1013 - case serialize: goto serialize_##name;\  
1014 - case unserialize: goto unserialize_##name;\  
1015 - case bit_width: goto bit_width_##name;\  
1016 - case indirect_type: goto indirect_type_##name;\  
1017 - case vcopy: goto vcopy_##name;\  
1018 - default: internal_error("Unknown term",term); }\  
1019 -  
1020 -  
1021 -#define interp_switch(head,name)\  
1022 - switch(car(head)) {\  
1023 - case alt_number: goto alt_number_##name;\  
1024 - case protect: goto protect_##name;\  
1025 - case lock: goto lock_##name;\  
1026 - case avm: goto avm_##name;\  
1027 - case debug_avm: goto debug_avm_##name;\  
1028 - case terminal: goto terminal_##name;\  
1029 - case operation: goto operation_##name;\  
1030 - case string: goto string_##name;\  
1031 - case anb_int32: goto int32_##name;\  
1032 - case small_datum: goto small_datum_##name;\  
1033 - case fpnum: goto fpnum_##name;\  
1034 - case local: goto local_##name;\  
1035 - case app: goto app_##name;\  
1036 - case cond: goto cond_##name;\  
1037 - case select_cond_interp: goto select_cond_interp_##name;\  
1038 - case with: goto with_##name;\  
1039 - case constructor: goto constructor_##name;\  
1040 - case anb_read: goto anb_read_##name;\  
1041 - case anb_write: goto anb_write_##name;\  
1042 - case wait_for: goto wait_for_##name;\  
1043 - case delegate: goto delegate_##name;\  
1044 - case serialize: goto serialize_##name;\  
1045 - case unserialize: goto unserialize_##name;\  
1046 - case bit_width: goto bit_width_##name;\  
1047 - case indirect_type: goto indirect_type_##name;\  
1048 - case vcopy: goto vcopy_##name;\  
1049 - default: internal_error("Unknown interpretation head",head); }\  
1050 - 988 +
1051 989
1052 extern int length(Expr list); 990 extern int length(Expr list);
1053 991
@@ -1470,7 +1408,7 @@ extern Expr _symbols_in_interp(Expr); @@ -1470,7 +1408,7 @@ extern Expr _symbols_in_interp(Expr);
1470 debug(implems[id].offline_code); } while(0) 1408 debug(implems[id].offline_code); } while(0)
1471 1409
1472 1410
1473 -extern Expr _debug(char *,Expr, char *filename, int line); 1411 +extern Expr _debug(const char *,Expr, char *filename, int line);
1474 extern void _debug_nl(char *file, int line); 1412 extern void _debug_nl(char *file, int line);
1475 extern void _debug_msg(char *msg); 1413 extern void _debug_msg(char *msg);
1476 1414
@@ -1916,7 +1854,8 @@ extern const char *msgtext_unused_named_resurgent[]; @@ -1916,7 +1854,8 @@ extern const char *msgtext_unused_named_resurgent[];
1916 extern const char *msgtext_duplicate_type_name[]; 1854 extern const char *msgtext_duplicate_type_name[];
1917 extern const char *msgtext_replaced_by[]; 1855 extern const char *msgtext_replaced_by[];
1918 extern const char *msgtext_undefined_macro[]; 1856 extern const char *msgtext_undefined_macro[];
1919 - 1857 +extern const char *msgtext_priority_not_word8[];
  1858 +extern const char *msgtext_priority_ambiguous[];
1920 1859
1921 1860
1922 #ifdef __cplusplus 1861 #ifdef __cplusplus
anubis_dev/compiler/src/compile.c
@@ -2985,6 +2985,66 @@ Expr compile_term(Expr head, @@ -2985,6 +2985,66 @@ Expr compile_term(Expr head,
2985 2985
2986 /*---------------------------------------------------------------------------*/ 2986 /*---------------------------------------------------------------------------*/
2987 2987
  2988 + case delegatep:
  2989 + {
  2990 + /* (delegate <lc> <head priority> <head (delegated)> . <head (body)>) */
  2991 +
  2992 + /*
  2993 + same as 'delegate' but with priority. The priority level must be computed
  2994 + first (not push into the stack). Uses 'startp' instead of 'start'
  2995 + should produce this:
  2996 +
  2997 + <d virtual copies in stack of parent machine>
  2998 + [priority] priority in R
  2999 + startp d a start a machine with priority (in R), d items in the stack
  3000 + and jump to 'a'
  3001 +
  3002 + [delegated]
  3003 + <d virtual deletions in stack of child machine>
  3004 + <deletion of R> (type is that of delegated)
  3005 +
  3006 + finish will stop the child machine
  3007 +
  3008 + label a:
  3009 + [body]
  3010 +
  3011 +
  3012 + When 'finished' is executed, there are still 2 words in the stack. Indeed,
  3013 + 'get_del_code_from_ctxt' does not generate an instruction for deleting the last 'ret'
  3014 + of the context. Furthermore, an initial 0 has been pushed into the stack by 'start'.
  3015 +
  3016 + */
  3017 + int d = length(ctxt);
  3018 + Expr a = new_addr_name(labs_none,0);
  3019 + Expr before_start = get_before_start_code(ctxt,env);
  3020 + Expr priority_code = compile_term(third(head),ctxt,env,nil);
  3021 + Expr delegated_code = compile_term(forth(head),ctxt,env,nil);
  3022 + Expr virtual_deletions = get_del_code_from_ctxt(ctxt,env);
  3023 + Expr body_code = compile_term(cdr4(head),ctxt,env,end_code);
  3024 +
  3025 + code = mcons3(finish,
  3026 + cons(label,a),
  3027 + remove_check_stack(body_code));
  3028 +
  3029 + code = cons(get_del_instr(type_from_interpretation(third(head),env),env),code); /* deleting R */
  3030 + /* actually, deleting R is not useful because the type of the datum in R is 'One' */
  3031 + assert(car(code) == no_instr);
  3032 + code = append(virtual_deletions,code);
  3033 + code = cons(cons(comment,new_string("deleting initial stack content")),code);
  3034 + code = append(delegated_code,code);
  3035 +
  3036 + code = cons(mcons3(startp,new_integer(d),a),code);
  3037 + code = append(priority_code,code);
  3038 + code = cons(cons(comment,new_string("computing priority level of new process")),code);
  3039 + code = append(before_start,code);
  3040 + code = cons(cons(check_stack,new_integer(stack_needs(body_code))),code);
  3041 + }
  3042 + break;
  3043 +
  3044 +
  3045 +
  3046 + /*---------------------------------------------------------------------------*/
  3047 +
2988 case serialize: 3048 case serialize:
2989 case tempserialize: 3049 case tempserialize:
2990 { 3050 {
anubis_dev/compiler/src/description.text
@@ -656,7 +656,8 @@ @@ -656,7 +656,8 @@
656 (of_type <lc> <type> . <term>) (explicit typing) 656 (of_type <lc> <type> . <term>) (explicit typing)
657 (string <lc> . <string>) (<string> is a Lisp-like string) 657 (string <lc> . <string>) (<string> is a Lisp-like string)
658 (with <lc> <symbol> <value> . <term>) 658 (with <lc> <symbol> <value> . <term>)
659 - (delegate <lc> <term> . <term>) 659 + (delegate <lc> <term> . <term>) (obsoleted by delegatep)
  660 + (delegatep <lc> <term> <term> . <term>) (delegate (priority) delegated, body)
660 (lambda <lc> <FArgs> . <term>) (|->) 661 (lambda <lc> <FArgs> . <term>) (|->)
661 (rec_lambda <lc> <name> <FArgs> . <term>) (|-f->) 662 (rec_lambda <lc> <name> <FArgs> . <term>) (|-f->)
662 (app <lc> <term> . <terms>) (applicative term) 663 (app <lc> <term> . <terms>) (applicative term)
@@ -743,6 +744,7 @@ @@ -743,6 +744,7 @@
743 (with <lc> <symbol> <head> . <head>) 744 (with <lc> <symbol> <head> . <head>)
744 745
745 (delegate <lc> <head> . <head>) 746 (delegate <lc> <head> . <head>)
  747 + (delegatep <lc> <head> <head> . <head>)
746 (serialize <lc> . <head>) 748 (serialize <lc> . <head>)
747 (unserialize <lc> <type> . <head>) 749 (unserialize <lc> <type> . <head>)
748 750
@@ -1438,7 +1440,8 @@ @@ -1438,7 +1440,8 @@
1438 1440
1439 *** (2.3.5.8) Starting a new virtual machine. 1441 *** (2.3.5.8) Starting a new virtual machine.
1440 1442
1441 - (start <depth> . <addr>) 1443 + (start <depth> . <addr>) (obsoleted by startp)
  1444 + (startp <priority> <depth> . <addr>)
1442 1445
1443 This instruction is generated by the keyword 'delegate' and starts a new virtual 1446 This instruction is generated by the keyword 'delegate' and starts a new virtual
1444 machine. '<depth>' is the number of slots on top of the stack of the old machine which 1447 machine. '<depth>' is the number of slots on top of the stack of the old machine which
anubis_dev/compiler/src/expr.cpp
@@ -216,6 +216,9 @@ Expr pcons(Expr x, Expr y) @@ -216,6 +216,9 @@ Expr pcons(Expr x, Expr y)
216 /* saving an expression in the permanent zone */ 216 /* saving an expression in the permanent zone */
217 Expr save(Expr x) 217 Expr save(Expr x)
218 { 218 {
  219 +
  220 + //debug(x);
  221 +
219 if (is_tpair(x)) 222 if (is_tpair(x))
220 { 223 {
221 if (car(x) == anb_int32) 224 if (car(x) == anb_int32)
@@ -1155,7 +1158,7 @@ int sprint_tail(char *filep, Expr expr) @@ -1155,7 +1158,7 @@ int sprint_tail(char *filep, Expr expr)
1155 1158
1156 int currently_debugging = 1; 1159 int currently_debugging = 1;
1157 1160
1158 -Expr _debug(char *name, Expr expr, char * filename, int line) 1161 +Expr _debug(const char *name, Expr expr, char * filename, int line)
1159 { 1162 {
1160 if (currently_debugging) 1163 if (currently_debugging)
1161 { 1164 {
anubis_dev/compiler/src/grammar.y
@@ -691,7 +691,8 @@ Term: yy__alert { alert_obsolete($1); @@ -691,7 +691,8 @@ Term: yy__alert { alert_obsolete($1);
691 | yy__with yy__tilde yy__equals Term yy__comma WithTerm { $$ = mcons5(with,$3,$2,$4,$6); } 691 | yy__with yy__tilde yy__equals Term yy__comma WithTerm { $$ = mcons5(with,$3,$2,$4,$6); }
692 | yy__checking_every Term yy__milliseconds yy__comma yy__wait_for Term yy__then Term 692 | yy__checking_every Term yy__milliseconds yy__comma yy__wait_for Term yy__then Term
693 { $$ = mcons5(wait_for,$1,$6,$2,$8); } 693 { $$ = mcons5(wait_for,$1,$6,$2,$8); }
694 -| yy__delegate Term yy__comma Term { $$ = mcons4(delegate,$1,$2,$4); } 694 +| yy__delegate Term yy__comma Term { $$ = mcons4(delegate,$1,$2,$4); }
  695 +| yy__delegate yy__lpar Term yy__rpar Term yy__comma Term { $$ = mcons5(delegatep,$1,$3,$5,$7); }
695 | yy__lpar FArgs1 yy__rpar yy__mapsto Term { $$ = mcons4(lambda,$4,$2,$5); } 696 | yy__lpar FArgs1 yy__rpar yy__mapsto Term { $$ = mcons4(lambda,$4,$2,$5); }
696 | yy__lpar FArgs1 yy__rpar yy__rec_mapsto Term { $$ = mcons5(rec_lambda,$3,$4,$2,$5); } 697 | yy__lpar FArgs1 yy__rpar yy__rec_mapsto Term { $$ = mcons5(rec_lambda,$3,$4,$2,$5); }
697 | yy__lbrace BEGINLBA yy__end_LBA { $$ = mcons3(byte_array,$1,$3); } 698 | yy__lbrace BEGINLBA yy__end_LBA { $$ = mcons3(byte_array,$1,$3); }
anubis_dev/compiler/src/interp.c
@@ -122,6 +122,15 @@ Expr delegate_interpretations (Expr lc, @@ -122,6 +122,15 @@ Expr delegate_interpretations (Expr lc,
122 Expr env, 122 Expr env,
123 Expr tvs); 123 Expr tvs);
124 124
  125 +Expr delegatep_interpretations (Expr lc,
  126 + Expr ttype,
  127 + Expr priority,
  128 + Expr delegated,
  129 + Expr body,
  130 + Expr ctxt,
  131 + Expr env,
  132 + Expr tvs);
  133 +
125 Expr serialize_interpretations (Expr lc, 134 Expr serialize_interpretations (Expr lc,
126 int allow_serialize_Opaque, 135 int allow_serialize_Opaque,
127 Expr ttype, 136 Expr ttype,
@@ -2109,6 +2118,22 @@ term_interpretations(Expr ttype, /* required type for that term (may contai @@ -2109,6 +2118,22 @@ term_interpretations(Expr ttype, /* required type for that term (may contai
2109 env, 2118 env,
2110 tvs); 2119 tvs);
2111 } 2120 }
  2121 + break;
  2122 +
  2123 +
  2124 + case delegatep:
  2125 + {
  2126 + /* (delegatep <lc> <term> <term> . <term>) */
  2127 + term = cdr(term);
  2128 + result = delegatep_interpretations(car(term), /* lc */
  2129 + dummy,
  2130 + second(term), /* priority */
  2131 + third(term), /* delegated */
  2132 + cdr3(term), /* body */
  2133 + ctxt,
  2134 + env,
  2135 + tvs);
  2136 + }
2112 break; 2137 break;
2113 2138
2114 2139
@@ -4591,12 +4616,12 @@ Expr wait_for_interpretations (Expr lc, @@ -4591,12 +4616,12 @@ Expr wait_for_interpretations (Expr lc,
4591 4616
4592 4617
4593 Expr delegate_interpretations (Expr lc, 4618 Expr delegate_interpretations (Expr lc,
4594 - Expr ttype,  
4595 - Expr delegated,  
4596 - Expr body,  
4597 - Expr ctxt,  
4598 - Expr env,  
4599 - Expr tvs) 4619 + Expr ttype,
  4620 + Expr delegated,
  4621 + Expr body,
  4622 + Expr ctxt,
  4623 + Expr env,
  4624 + Expr tvs)
4600 { 4625 {
4601 /* 'delegate u, v' is correct if 'u' has a unique interpretation of type 4626 /* 'delegate u, v' is correct if 'u' has a unique interpretation of type
4602 'One', and if 'v' may be interpreted. */ 4627 'One', and if 'v' may be interpreted. */
@@ -4613,7 +4638,7 @@ Expr delegate_interpretations (Expr lc, @@ -4613,7 +4638,7 @@ Expr delegate_interpretations (Expr lc,
4613 while (consp(aux)) 4638 while (consp(aux))
4614 { 4639 {
4615 if (type_from_interpretation(car(car(aux)),cdr(car(aux))) == pdstr_One) 4640 if (type_from_interpretation(car(car(aux)),cdr(car(aux))) == pdstr_One)
4616 - one_deleg_ints = cons(car(aux),one_deleg_ints); 4641 + one_deleg_ints = cons(car(aux),one_deleg_ints);
4617 aux = cdr(aux); 4642 aux = cdr(aux);
4618 } 4643 }
4619 4644
@@ -4656,11 +4681,133 @@ Expr delegate_interpretations (Expr lc, @@ -4656,11 +4681,133 @@ Expr delegate_interpretations (Expr lc,
4656 { 4681 {
4657 /* each interpretation head is (delegate lc Ideleg . Ibody) */ 4682 /* each interpretation head is (delegate lc Ideleg . Ibody) */
4658 result = cons(cons(mcons4(delegate, 4683 result = cons(cons(mcons4(delegate,
4659 - lc,  
4660 - car(car(one_deleg_ints)),  
4661 - car(car(body_ints))),  
4662 - cdr(car(body_ints))),  
4663 - result); 4684 + lc,
  4685 + car(car(one_deleg_ints)),
  4686 + car(car(body_ints))),
  4687 + cdr(car(body_ints))),
  4688 + result);
  4689 + body_ints = cdr(body_ints);
  4690 + }
  4691 + return result;
  4692 +}
  4693 +
  4694 +
  4695 +
  4696 +Expr delegatep_interpretations (Expr lc,
  4697 + Expr ttype,
  4698 + Expr priority,
  4699 + Expr delegated,
  4700 + Expr body,
  4701 + Expr ctxt,
  4702 + Expr env,
  4703 + Expr tvs)
  4704 +{
  4705 + /* 'delegate u, v' is correct if 'u' has a unique interpretation of type
  4706 + 'One', and if 'v' may be interpreted. */
  4707 +
  4708 + Expr priority_ints, word8_priority_ints, deleg_ints, one_deleg_ints, body_ints, aux, result;
  4709 +
  4710 + /* interpert priority (its type must be Word8) */
  4711 + priority_ints = term_interpretations(dummy,priority,ctxt,env,tvs,0);
  4712 + if (priority_ints == nil) return nil;
  4713 +
  4714 + /* select only those interpretations which are of type 'Word8' */
  4715 + aux = priority_ints;
  4716 + word8_priority_ints = nil;
  4717 + while (consp(aux))
  4718 + {
  4719 + if (type_from_interpretation(car(car(aux)),cdr(car(aux))) == pdstr_Word8)
  4720 + word8_priority_ints = cons(car(aux),word8_priority_ints);
  4721 + aux = cdr(aux);
  4722 + }
  4723 +
  4724 + /* we should have at least one interpretation of type 'Word8' */
  4725 + if (word8_priority_ints == nil)
  4726 + {
  4727 + if (show_errors)
  4728 + {
  4729 + err_line_col(lc,"E123",
  4730 + msgtext_priority_not_word8[0]);
  4731 + show_interpretations_types(errfile,priority_ints);
  4732 + }
  4733 + return nil;
  4734 + }
  4735 +
  4736 + /* we should not have several interpretations of type 'Word8' */
  4737 + if (cdr(word8_priority_ints) != nil)
  4738 + {
  4739 + if (show_errors)
  4740 + {
  4741 + err_line_col(lc,"E124",
  4742 + msgtext_priority_ambiguous[0]);
  4743 + show_simple_ambiguity(errfile,word8_priority_ints);
  4744 + }
  4745 + return nil;
  4746 + }
  4747 +
  4748 + /* update 'env' with the environment of the unique interpretation of
  4749 + the delegated term */
  4750 + env = cdr(car(word8_priority_ints));
  4751 +
  4752 + /* interpret delegated (its type must be 'One') */
  4753 + deleg_ints = term_interpretations(dummy,delegated,ctxt,env,tvs,0);
  4754 + if (deleg_ints == nil) return nil;
  4755 +
  4756 + /* select only those interpretations which are of type 'One' */
  4757 + aux = deleg_ints;
  4758 + one_deleg_ints = nil;
  4759 + while (consp(aux))
  4760 + {
  4761 + if (type_from_interpretation(car(car(aux)),cdr(car(aux))) == pdstr_One)
  4762 + one_deleg_ints = cons(car(aux),one_deleg_ints);
  4763 + aux = cdr(aux);
  4764 + }
  4765 +
  4766 + /* we should have at least one interpretation of type 'One' */
  4767 + if (one_deleg_ints == nil)
  4768 + {
  4769 + if (show_errors)
  4770 + {
  4771 + err_line_col(lc,"E057",
  4772 + msgtext_delegated_not_one[0]);
  4773 + show_interpretations_types(errfile,deleg_ints);
  4774 + }
  4775 + return nil;
  4776 + }
  4777 +
  4778 + /* we should not have several interpretations of type 'One' */
  4779 + if (cdr(one_deleg_ints) != nil)
  4780 + {
  4781 + if (show_errors)
  4782 + {
  4783 + err_line_col(lc,"E058",
  4784 + msgtext_delegated_ambiguous[0]);
  4785 + show_simple_ambiguity(errfile,one_deleg_ints);
  4786 + }
  4787 + return nil;
  4788 + }
  4789 +
  4790 + /* update 'env' with the environment of the unique interpretation of
  4791 + the delegated term */
  4792 + env = cdr(car(one_deleg_ints));
  4793 +
  4794 + /* now, we have to interpret the 'body' term (in the same context) */
  4795 + body_ints = term_interpretations(dummy,body,ctxt,env,tvs,0);
  4796 + if (body_ints == nil) return nil;
  4797 +
  4798 + /* finally, we have one interpretation for each interpretation of the
  4799 + body term */
  4800 + result = nil;
  4801 + while (consp(body_ints))
  4802 + {
  4803 + /* each interpretation head is (delegatep lc Ipriority Ideleg . Ibody) */
  4804 + result = cons(cons(mcons5(delegatep,
  4805 + lc,
  4806 + car(car(word8_priority_ints)),
  4807 + car(car(one_deleg_ints)),
  4808 + car(car(body_ints))),
  4809 + cdr(car(body_ints))),
  4810 + result);
4664 body_ints = cdr(body_ints); 4811 body_ints = cdr(body_ints);
4665 } 4812 }
4666 return result; 4813 return result;
@@ -4668,6 +4815,10 @@ Expr delegate_interpretations (Expr lc, @@ -4668,6 +4815,10 @@ Expr delegate_interpretations (Expr lc,
4668 4815
4669 4816
4670 4817
  4818 +
  4819 +
  4820 +
  4821 +
4671 #ifdef toto 4822 #ifdef toto
4672 Expr set_interpretations (Expr lc, 4823 Expr set_interpretations (Expr lc,
4673 Expr ttype, 4824 Expr ttype,
anubis_dev/compiler/src/msgtexts.c
@@ -435,10 +435,21 @@ const char *msgtext_wait_milliseconds_ambiguous[] = @@ -435,10 +435,21 @@ const char *msgtext_wait_milliseconds_ambiguous[] =
435 { " The milliseconds delay after 'wait for' is ambiguous,\n for the following reason:\n" }; 435 { " The milliseconds delay after 'wait for' is ambiguous,\n for the following reason:\n" };
436 436
437 const char *msgtext_delegated_not_one[] = 437 const char *msgtext_delegated_not_one[] =
438 -{ " The term after 'delegate' is not of\n type 'One'. The types found are:\n" }; 438 +{ " The delegated term after 'delegate' is not of type 'One'.\n"
  439 + " The types found are:\n"
  440 +};
  441 +
  442 +const char *msgtext_priority_not_word8[] =
  443 +{
  444 + " The priority level after 'delegate' is not of type 'Word8'.\n"
  445 + " The types found are:\n"
  446 +};
439 447
440 const char *msgtext_delegated_ambiguous[] = 448 const char *msgtext_delegated_ambiguous[] =
441 -{ " The term after 'delegate' is ambiguous,\n for the following reason:\n" }; 449 +{ " The delegated term after 'delegate' is ambiguous,\n for the following reason:\n" };
  450 +
  451 +const char *msgtext_priority_ambiguous[] =
  452 +{ " The priority level after 'delegate' is ambiguous,\n for the following reason:\n" };
442 453
443 const char *msgtext_select_cond_incompatible_types[] = 454 const char *msgtext_select_cond_incompatible_types[] =
444 { " In the conditional, the type of the case body\n" 455 { " In the conditional, the type of the case body\n"
anubis_dev/compiler/src/optimize.c
@@ -1048,6 +1048,16 @@ Expr optimize_definition_code(Expr code) @@ -1048,6 +1048,16 @@ Expr optimize_definition_code(Expr code)
1048 code = optimize_copy_del(code); 1048 code = optimize_copy_del(code);
1049 } while (changed); 1049 } while (changed);
1050 1050
  1051 + /* drive back del_stack instructions to the end of code */
  1052 +#if 0
  1053 + if (optimization_flags & opt_flag_drive_back)
  1054 + do
  1055 + {
  1056 + changed = 0;
  1057 + code = drive_back(code);
  1058 + } while (changed);
  1059 +#endif
  1060 +
1051 /* groups of instructions optimization */ 1061 /* groups of instructions optimization */
1052 #if 1 1062 #if 1
1053 if (optimization_flags & opt_flag_grp) 1063 if (optimization_flags & opt_flag_grp)
anubis_dev/compiler/src/typetools.c
@@ -301,6 +301,10 @@ Expr _type_from_interpretation(Expr head, Expr env) @@ -301,6 +301,10 @@ Expr _type_from_interpretation(Expr head, Expr env)
301 result = type_from_interpretation(cdr3(head),env); 301 result = type_from_interpretation(cdr3(head),env);
302 break; 302 break;
303 303
  304 + case delegatep: /* (delegate <lc> <head> <head> . <head>) */
  305 + result = type_from_interpretation(cdr4(head),env);
  306 + break;
  307 +
304 /* 308 /*
305 case omega_true: 309 case omega_true:
306 case omega_false: 310 case omega_false:
anubis_dev/compiler/src/vminstr.c
@@ -292,6 +292,7 @@ int instruction_size(Expr instr, int offset) @@ -292,6 +292,7 @@ int instruction_size(Expr instr, int offset)
292 case mvar_slots_del_mixed: 292 case mvar_slots_del_mixed:
293 case select_index_indirect: 293 case select_index_indirect:
294 case start: 294 case start:
  295 + case startp:
295 case type_mixed: 296 case type_mixed:
296 case indirect_type_mixed: 297 case indirect_type_mixed:
297 case del_stack_struct_ptr: 298 case del_stack_struct_ptr:
@@ -1482,6 +1483,13 @@ void translate_instruction(U8 *code_addr, @@ -1482,6 +1483,13 @@ void translate_instruction(U8 *code_addr,
1482 *ptr += sizeof(U32); 1483 *ptr += sizeof(U32);
1483 break; 1484 break;
1484 1485
  1486 + case startp: /* (start <depth> . <addr>) */
  1487 + *((*ptr)++) = i_startp;
  1488 + *((*ptr)++) = integer_value(second(instr));
  1489 + *(((U32 *)(*ptr))) = offsets[integer_value(cdr2(instr))];
  1490 + *ptr += sizeof(U32);
  1491 + break;
  1492 +
1485 case _switch: /* (switch a1 ... ak) --> 1493 case _switch: /* (switch a1 ... ak) -->
1486 i_switch k a1 ... ak */ 1494 i_switch k a1 ... ak */
1487 { 1495 {
anubis_dev/include/bytecode.h
@@ -168,6 +168,7 @@ typedef enum @@ -168,6 +168,7 @@ typedef enum
168 item(read_locvar)\ 168 item(read_locvar)\
169 item(write_locvar)\ 169 item(write_locvar)\
170 item(start)\ 170 item(start)\
  171 + item(startp)\
171 item(finish)\ 172 item(finish)\
172 item(copy_stack_ptr)\ 173 item(copy_stack_ptr)\
173 item(copy_stack_mixed)\ 174 item(copy_stack_mixed)\
anubis_dev/include/minver.h
1 #define maj_version (1) 1 #define maj_version (1)
2 -#define min_version (13)  
3 -#define rel_version (5) 2 +#define min_version (14)
  3 +#define rel_version (0)
4 #define build_version (0) 4 #define build_version (0)
5 5
6 6
anubis_dev/library/web/torture_server.anubis
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 6
7 7
8 8
9 - 9 +read tools/time.anubis
10 read web/http_get.anubis 10 read web/http_get.anubis
11 11
12 12
@@ -19,6 +19,7 @@ define One @@ -19,6 +19,7 @@ define One
19 ) = 19 ) =
20 print(to_decimal(n)+"/"+to_decimal(i)+" "); 20 print(to_decimal(n)+"/"+to_decimal(i)+" ");
21 forget(http_get(addr,"/",[],[])); 21 forget(http_get(addr,"/",[],[]));
  22 + //sleep(5000);
22 ask_pages(addr,n,i+1). 23 ask_pages(addr,n,i+1).
23 24
24 25
@@ -29,7 +30,7 @@ global define One @@ -29,7 +30,7 @@ global define One
29 ) = 30 ) =
30 with addr = if args is { [] then "127.0.0.1" , [ h . _] then h}, 31 with addr = if args is { [] then "127.0.0.1" , [ h . _] then h},
31 forget( 32 forget(
32 - delegate ask_pages(addr,0,0), 33 + delegate (247) ask_pages(addr,0,0),
33 delegate ask_pages(addr,1,0), 34 delegate ask_pages(addr,1,0),
34 delegate ask_pages(addr,2,0), 35 delegate ask_pages(addr,2,0),
35 delegate ask_pages(addr,3,0), 36 delegate ask_pages(addr,3,0),
anubis_dev/manuals/en/Anubis-doc-1-13.pdf
No preview for this file type
anubis_dev/manuals/en/Anubis-doc-1-13.tex
@@ -598,7 +598,7 @@ @@ -598,7 +598,7 @@
598 {\sl Alain Prouté}\\ 598 {\sl Alain Prouté}\\
599 \ \\ 599 \ \\
600 Last revision of this text~: \today\\ 600 Last revision of this text~: \today\\
601 -Refers to version~: 1.13 601 +Refers to version 1.14 and subsequent versions
602 \end{center} 602 \end{center}
603 603
604 604
@@ -892,7 +892,25 @@ is &amp;&amp; with @@ -892,7 +892,25 @@ is &amp;&amp; with
892 \end{liste} 892 \end{liste}
893 893
894 894
895 -\section{The typing system} 895 +
  896 +\subsection{Syntactic considerations}
  897 +
  898 +
  899 +%
  900 +%
  901 +%
  902 +%
  903 +%
  904 +%
  905 +%
  906 +%
  907 +%
  908 +%
  909 +%
  910 +%
  911 +%
  912 +%
  913 +\section{The system of types}
896 The typing system is the very heart of the Anubis programming paradigm. The safety of the code 914 The typing system is the very heart of the Anubis programming paradigm. The safety of the code
897 you produce is mainly a consequence of the design of the typing system, just as the soundness of a 915 you produce is mainly a consequence of the design of the typing system, just as the soundness of a
898 bridge depends on the design of its piers. 916 bridge depends on the design of its piers.
@@ -964,6 +982,25 @@ see below. @@ -964,6 +982,25 @@ see below.
964 % 982 %
965 % 983 %
966 % 984 %
  985 +\subsection{Primitive types}
  986 +
  987 +
  988 +
  989 +%
  990 +%
  991 +%
  992 +%
  993 +%
  994 +%
  995 +%
  996 +%
  997 +%
  998 +%
  999 +%
  1000 +%
  1001 +%
  1002 +%
  1003 +%
967 \subsection{Defining named types} 1004 \subsection{Defining named types}
968 We now enter into the details of the definition of a new data type (named type) as in the example above 1005 We now enter into the details of the definition of a new data type (named type) as in the example above
969 (first tool). 1006 (first tool).
@@ -985,7 +1022,7 @@ We now enter into the details of the definition of a new data type (named type) @@ -985,7 +1022,7 @@ We now enter into the details of the definition of a new data type (named type)
985 % 1022 %
986 % 1023 %
987 % 1024 %
988 -\subsection{Using functional types} 1025 +\subsection{Functional types}
989 1026
990 1027
991 % 1028 %
@@ -1189,6 +1226,132 @@ a micro-context. Such a pair is generally called a ``closure&#39;&#39; in computer scien @@ -1189,6 +1226,132 @@ a micro-context. Such a pair is generally called a ``closure&#39;&#39; in computer scien
1189 \subsection{Schemas}\mylabel{sec:schemas} 1226 \subsection{Schemas}\mylabel{sec:schemas}
1190 1227
1191 1228
  1229 +
  1230 +\section{Objects}
  1231 +
  1232 +
  1233 +\subsection{Types versus classes and data versus objects}
  1234 +Object oriented programming has introduced the notions of ``object'' and ``class'', which are often
  1235 +thought of as generalizations of the notions of ``datum'' and ``type''. I don't agree with this point
  1236 +of view because data and objects have very different behaviors. In particular, I think that the
  1237 +``all object'' paradigm, adopted by several computer languages, is not at all a good idea, because
  1238 +objects are much more difficult to manipulate than data. Doing so puts on data an unnecessary burden.
  1239 +Of course, if you don't perceive the difference between an object and a datum, the above discussion
  1240 +is probably meaningless for you. In any case, I discuss this difference below.
  1241 +
  1242 +First of all, let's take a real life example. Consider the following two ``things''~: (1) a number (for example,
  1243 +the number $\pi=3,1415\dots$), and (2) a chair~:
  1244 +\begin{center}
  1245 +\includegraphics[width=80mm]{pi_chair.png}
  1246 +\end{center}
  1247 +It should be obvious that these two ``things'' don't have the same behavior. For example, you can burn
  1248 +the chair, but it is very unlikely that you are able to burn the number $\pi$. Maybe, you can burn
  1249 +a piece of paper with $\pi$ printed on it, but you cannot burn the number itself. Unlike the chair,
  1250 +$\pi$ is undestroyable. This is a first difference, but there are many others.
  1251 +
  1252 +For example, you can have two ``identical'' chairs, more precisely two ``copies'' of the same chair, but
  1253 +what would it mean to have two copies of the number $\pi$~? I assure you that mathematicians never consider
  1254 +copies of the number $\pi$. They never say ``a number $\pi$'', but always ``the number $\pi$'', which is therefore
  1255 +unique, unlike the chair.
  1256 +
  1257 +As another example, it is clear that the chair shown above was made at some time in the past. It has
  1258 +a ``birth date''. Dou you thing that the number $\pi$ has a birth date~? For sure, there is a date (that
  1259 +we are unable to determine) at which this number was discovered on the planet earth. But the number $\pi$
  1260 + already existed before this date, and maybe was discovered earlier on another planet.
  1261 +
  1262 +As a conclusion regarding this example, we will say that {\sl the chair is an object}, and that
  1263 +{\sl the number $\pi$ is not an object}.
  1264 +
  1265 +Now, let's take an example more interesting for programmers. Consider again a number (say a 32 bits number,
  1266 +of type \code{Word32} in Anubis), and a network connection (of type \code{RWStream} in Anubis).
  1267 +Like the chair, a connection has a birth date, since in order to have a connection we need to ``open''
  1268 +a connection. The time at which we open the connection is its birth date. You can also destroy (burn~!) the
  1269 +connection just by ``closing'' it.
  1270 +
  1271 +
  1272 +
  1273 +\subsection{Dynamic variables}
  1274 +Anubis has a special kind of objects called ``dynamic variables''. In programming, the word ``variable''
  1275 +generally represents some place in memory where a datum of a certain type can be stored. For example,
  1276 +in the language C, you can write~:
  1277 +\begin{verbatim}
  1278 +int i;
  1279 +\end{verbatim}
  1280 +which means that you want some place able to contain an integer (of type {\tt int} in this case). Notice
  1281 +that in the above example, this place is considered as ``empty'' since, I did not give it an ``initial value'',
  1282 +but the important thing is that you can put a value (an ``int'') into it, and that you can also change this value at will
  1283 +during the execution of your program.
  1284 +Notice that {\tt i} is called a ``variable'' just because its content may vary.
  1285 +
  1286 +In the language C, and many other languages since the paradigm of C has spread almost everywhere in programming languages,
  1287 +such a variable is either ``local'' or ``global'' depending on the fact that it is declared within the body
  1288 +of a function or not.
  1289 +In Anubis, you don't have local variables of the above sort. This is also linked to the fact that Anubis has no
  1290 +notion of loop (at least explicitely). See the discussion on functions for more details on this question.
  1291 +Anubis also does not have global variables in the above sens. There are global notions in Anubis, but none deserves the
  1292 +name of ``variable''.
  1293 +
  1294 +Before going further, remark that a variable in the above sens (i.e. a place whose content may change during execution)
  1295 +cannot be a datum, but is necessarily an object. Indeed, you can have two variables, for example declared in C like this~:
  1296 +\begin{verbatim}
  1297 +int i = 3;
  1298 +int j = 3;
  1299 +\end{verbatim}
  1300 +which are in some sens ``identical'', because they are of the same type and contain the same number. Nevertheless, you know that they
  1301 +are not identical, for example because a confusion between them is most probably a bug. These two variables are like two chairs of the same model.
  1302 +They are at the same time ``identical'' (same type, same content), and distinct because they are not at the same place in memory,
  1303 +just like two ``identical'' chairs cannot be at the same place in your dinning room (according to Pauli's principle, since they are
  1304 +made of fermions).
  1305 +
  1306 +Probably, a variable like {\tt i} above could better be called a `container'', because its only
  1307 +purpose is to ``contain'' something. However (again~!), what should better be called a container is not {\tt i}
  1308 +but {\tt \&i}, the ``address'' of {\tt i}. Indeed, in the language C, {\tt i} does not represent the place where
  1309 +the number is stored, but the very number stored in this place, i.e. only the content of the container.
  1310 +Nevertheless, this is still {\tt i} which is called a ``variable'' and not {\tt \&i}, probably because what may vary
  1311 +is not the container itself but its content.
  1312 +
  1313 +As a conclusion of the above discussion, we can say for sure that the ``container'' (aka. the ``variable'') is an object.
  1314 +
  1315 +Now, comming back to Anubis, we have the notion of ``dynamic variable'', which designates a container (hence an object),
  1316 +which is at the same time ``variable'' (its content may change during execution) and ``dynamic'' (it can be created/destroyed
  1317 +during execution).
  1318 +
  1319 +The purpose of dynamic variables in Anubis is not to be used as storage places for making abstract computations. In Anubis
  1320 +(and in functionnal languages in general), abstract computations must better avoid the use of any object. Avoiding the use
  1321 +of any object entails that the program is deterministic. This has the important consequence that it is more easy to understand,
  1322 +and consequently less error prone.
  1323 +
  1324 +The main uses of dynamic variables is (1) the creation of objects, (2) the communication between Anubis processes.
  1325 +Below we first explain the syntax and semantics of dynamic variables, and in the subsequent sections we give examples
  1326 +of their uses.
  1327 +
  1328 +\subsubsection{Syntax and semantics}
  1329 +A dynamic variable able to contain a datum of type \code{T} is itself of class \code{Var(T)}. In order to create
  1330 +a dynamic variable of class \code{Var(T)}, you must provide an initial content (of type \code{T}). The command~:
  1331 +\begin{center}
  1332 +\code{var(\sconcept{term})}
  1333 +\end{center}
  1334 +(where \sconcept{term} is of type \code{T}) creates such a dynamic variable with initial content \sconcept{term}.
  1335 +Thus, a dynamic variable is never empty, so that ``reading'' its content cannot produce an error.
  1336 +
  1337 +If \code{v} is a dynamic variable of class \code{Var(T)}, \code{*v} (which is of type \code{T}) represents the
  1338 +content of the variable, and if you want to change the value of the variable, use the command~:
  1339 +\begin{center}
  1340 +\code{v <- \sconcept{term}}
  1341 +\end{center}
  1342 +where \sconcept{term} is the new content of \code{v}. The expression \code{v <- \sconcept{term}} is of type \code{One},
  1343 +so that it can be put in front of a semi-colon.
  1344 +
  1345 +
  1346 +\subsubsection{Creating objects}
  1347 +
  1348 +\subsubsection{Communication between Anubis processes}
  1349 +
  1350 +\subsubsection{Functions and encapsulation}
  1351 +
  1352 +
  1353 +
  1354 +
1192 % 1355 %
1193 % 1356 %
1194 % 1357 %
@@ -1293,7 +1456,24 @@ by something needing the body of their definition, a macro or an inline function @@ -1293,7 +1456,24 @@ by something needing the body of their definition, a macro or an inline function
1293 it is defined (hence can also not be recursive). Unlike ordinary functions, declaring it is not enough for using~it. 1456 it is defined (hence can also not be recursive). Unlike ordinary functions, declaring it is not enough for using~it.
1294 1457
1295 1458
  1459 +\subsection{Serializing/unserializing data}
  1460 +
1296 1461
  1462 +
  1463 +%
  1464 +%
  1465 +%
  1466 +%
  1467 +%
  1468 +%
  1469 +%
  1470 +%
  1471 +%
  1472 +%
  1473 +%
  1474 +%
  1475 +%
  1476 +%
1297 \subsection{Primary and secondary modules (\code{load\_adm})} 1477 \subsection{Primary and secondary modules (\code{load\_adm})}
1298 Each paragraph beginning by the keyword \code{global} produces a so-called ``module'', precisely, 1478 Each paragraph beginning by the keyword \code{global} produces a so-called ``module'', precisely,
1299 an ``Anubis dynamic module'' (aka ``adm'') which is stored by the compiler into a file with 1479 an ``Anubis dynamic module'' (aka ``adm'') which is stored by the compiler into a file with
@@ -1358,7 +1538,7 @@ it is possible to load a secondary module. It is of course possible to make this @@ -1358,7 +1538,7 @@ it is possible to load a secondary module. It is of course possible to make this
1358 as shown by the web server defined in \code{library/web/dynamic\_http\_server.anubis}. This program 1538 as shown by the web server defined in \code{library/web/dynamic\_http\_server.anubis}. This program
1359 looks for secondary modules whose name matches the mask \code{*\_web\_site.adm}, and automatically 1539 looks for secondary modules whose name matches the mask \code{*\_web\_site.adm}, and automatically
1360 loads them, or reloads them when they are recompiled, thus enabling to update the code of a web site 1540 loads them, or reloads them when they are recompiled, thus enabling to update the code of a web site
1361 -without stopping the web server. Even more, the new version and the previous version can work conccurently 1541 +without stopping the web server. Even more, the new version and the previous version can work concurrently
1362 if a request answered by the previous version is still being serviced while the new version is already loaded 1542 if a request answered by the previous version is still being serviced while the new version is already loaded
1363 and servicing another client. 1543 and servicing another client.
1364 1544
@@ -1521,48 +1701,54 @@ several so-called ``Anubis processes&#39;&#39; (``process&#39;&#39; for short). These processes @@ -1521,48 +1701,54 @@ several so-called ``Anubis processes&#39;&#39; (``process&#39;&#39; for short). These processes
1521 of the underlying operating system (Unix, Windows, \dots). 1701 of the underlying operating system (Unix, Windows, \dots).
1522 1702
1523 \subsubsection{Features and caveats} 1703 \subsubsection{Features and caveats}
  1704 +Anubis is multitasking because when I started to develop it around the year 2000, I had the idea to try to
  1705 +construct a small operating system (just as an exercice for fun). I abandonned this idea later (maybe not for ever),
  1706 +but because of this, Anubis has a scheduler
  1707 +and is able to launch many processes within a single process of the host system.
  1708 +
  1709 +This has advantages and disadvantages. The main avantage is that launching an Anubis process requires far
  1710 +less memory than launching a process of the underlying system. This is mainly because all Anubis processes
  1711 +running in a single instance of \code{anbexec} share the same memory heap. Of course, each process has
  1712 +its own stack (which is small when the process is created but which can grown automatically), but
  1713 +all data which are not directly in the stack are in the common pool of memory. In particular, Anubis
  1714 +processes can share dynamic variables that they use as ``mailboxes'' for communicating.
  1715 +
  1716 +This design allows for example the HTTP server defined in \code{library/web} to serve many clients
  1717 +simultaneously while still be running in a single thread of the host system. This is good for both speed
  1718 +and memory usage.
  1719 +
  1720 +The main disadvantage is that a single instance of \code{anbexec} cannot use several physical processors. But it
  1721 +is still possible to launch several instances of \code{anbexec} collaborating through local connections and
  1722 +run by different physical processors. Of course, this needs a special conception of the whole project. It is
  1723 +not impossible that in the future Anubis is enhanced for being able to use several physical processors
  1724 +transparently.
  1725 +
  1726 +
  1727 +
1524 1728
1525 \subsubsection{Syntax and semantics} 1729 \subsubsection{Syntax and semantics}
1526 In order to launch an Anubis process, use the keyword \code{delegate}. There are two distinct syntaxes 1730 In order to launch an Anubis process, use the keyword \code{delegate}. There are two distinct syntaxes
1527 for delegate~: 1731 for delegate~:
1528 \begin{dcode} 1732 \begin{dcode}
1529 - delegate <term>, <term> // first form  
1530 - delegate (<term>) <term> // second form 1733 +\hs delegate \sconcept{term}, \sconcept{term}\\
  1734 +\hs delegate (\sconcept{term}) \sconcept{term}, \sconcept{term}
1531 \end{dcode} 1735 \end{dcode}
1532 -with distinct semantics.  
1533 -\begin{liste}  
1534 -\item First form~: Execution of \code{delegate a, b} works as follows~: 1736 +The execution of \code{delegate a, b} works as follows~:
1535 \begin{liste} 1737 \begin{liste}
1536 - \item (1) a new Anubis process with priority 0 (background process) is created,  
1537 - \item (2) the term \code{a}, which must be of type \code{One}, is executed by this new process, 1738 + \item (1) a new Anubis process with the same priority level as the current process is created,
  1739 + \item (2) the term \code{a} (which must be of type \code{One}) is executed by this new process,
1538 \item (3) the current process executes \code{b}, 1740 \item (3) the current process executes \code{b},
1539 \item (4) the value returned by the whole expression \code{delegate a, b} is the value of~\code{b}. 1741 \item (4) the value returned by the whole expression \code{delegate a, b} is the value of~\code{b}.
1540 \end{liste} 1742 \end{liste}
1541 -  
1542 -\item Second form~: Execution of \code{delegate (p) a} works as follows~:  
1543 - \begin{liste}  
1544 - \item (1) a new Anubis process is created with priority level \code{p} (of type \code{Word8}),  
1545 - \item (2) the term \code{a}, which must be of type \code{One}, is executed by this new process,  
1546 - \item (3) the whole expression \code{delegate (p) a} returns immediately a datum of  
1547 - type \code{Process}, which identifies the new process.  
1548 - \end{liste}  
1549 -\end{liste}  
1550 -Remark that \code{delegate a, b} is equivalent to \code{forget(delegate (0) a); b}.  
1551 -  
1552 -Of course, the second form is more powerful than the first one, but the first one is easier to use if  
1553 -you don't need to control the priority of processes. Normally, you don't mix boths forms of \code{delegate}  
1554 -in the same project.  
1555 -  
1556 -\code{Process} is an opaque type. However, there are functions for manipulating processes. In particular,  
1557 -it is possible to change the priority level of a process during its execution.  
1558 - 1743 +The execution of \code{delegate (p) a, b} works in the same way except that the priority level of
  1744 +the new process is the minimum of the priority level of the current process and of the value of \code{p}
  1745 +(which is of type \code{Word8}).
1559 1746
1560 1747
1561 \subsubsection{Priority levels} 1748 \subsubsection{Priority levels}
1562 The priority level of an Anubis process is a datum of type \code{Word8}, i.e. an integer whose value ranges 1749 The priority level of an Anubis process is a datum of type \code{Word8}, i.e. an integer whose value ranges
1563 -from 0 to 255 (so, considered as positive or zero). Using the second form of \code{delegate}, you can set the priority of a process when it is created.  
1564 -This priority can later be changed dynamically (i.e. during execution of the process), but be careful about that because  
1565 -changing the priority of a process during execution can dramatically affect other processes. 1750 +from 0 to 255 (so, considered as positive or zero). Using the second form of \code{delegate}, you can set
  1751 +the priority of a process when it is created.
1566 1752
1567 The scheduler takes priority levels into account in the following manner. 1753 The scheduler takes priority levels into account in the following manner.
1568 1754
@@ -1575,85 +1761,41 @@ by the event puts itself back immediately into a sleeping state. @@ -1575,85 +1761,41 @@ by the event puts itself back immediately into a sleeping state.
1575 This said, we are now concerned only by running processes. Each running process is run with 1761 This said, we are now concerned only by running processes. Each running process is run with
1576 a ``credit'' computed by the scheduler. This credit is the maximal number of virtual machine 1762 a ``credit'' computed by the scheduler. This credit is the maximal number of virtual machine
1577 instructions the process is allowed to execute before it must give up. The credit cannot be more 1763 instructions the process is allowed to execute before it must give up. The credit cannot be more
1578 -than a given fixed value (which defaults to 500, but which can be changed using the option \code{-\sh-credit} with \code{anbexec}). 1764 +than a given fixed value (which defaults to 500, but which can be changed using the option \code{-\sh-credit} when
  1765 +launching \code{anbexec}).
1579 1766
1580 The credit for running a process is computed as follows (at each passage into the chain of processes)~: 1767 The credit for running a process is computed as follows (at each passage into the chain of processes)~:
1581 \begin{liste} 1768 \begin{liste}
1582 \item (1) the scheduler computes the maximum $M$ of the priority levels of all running processes, 1769 \item (1) the scheduler computes the maximum $M$ of the priority levels of all running processes,
1583 -\item (2) if the priority level of a process is less than or equal to $M-10$, it is not run,  
1584 -\item (3) if the priority level $L$ of a process is between $M-9$ (included) and $M$ (included), it is run with a  
1585 -credit of $D(1 - \frac{M-L}{10})$, where $D$ is the default (maximal) credit. 1770 +\item (2) if the priority level of a process is less than or equal to $M-16$, it is not run,
  1771 +\item (3) if the priority level $L$ of a process is between $M-15$ (included) and $M$ (included), it is run with a
  1772 +credit of $D(1 - \frac{M-L}{16})$, where $D$ is the default (maximal) credit.
1586 \end{liste} 1773 \end{liste}
1587 1774
1588 Examples~: 1775 Examples~:
1589 \begin{liste} 1776 \begin{liste}
1590 -\item We have two processes $A$ and $B$. 1777 +\item We have two processes $A$ and $B$, then~:
1591 \begin{liste} 1778 \begin{liste}
1592 - \item If $A$ has priority 50, and $B$ has priority $40$, $B$ must wait that $A$ is sleeping  
1593 - for running.  
1594 - \item If $A$ has priority 50 and $B$ has priority $45$, $B$ runs conccurently with $A$, but with half the credit of $A$ (i.e.  
1595 - $A$ runs twice faster than $B$).  
1596 - \item If $A$ has priority 50 and $B$ has priority $49$, $B$ runs ten percent slower than $A$. 1779 + \item If $A$ has priority $50$, and $B$ has priority $34$ or less, $B$ must wait that $A$ is sleeping
  1780 + for being allowed to run.
  1781 + \item If $A$ has priority $50$ and $B$ has priority $42$, $B$ runs concurrently with $A$, but with half the credit of $A$ (i.e.
  1782 + $A$ runs twice ``faster'' than $B$).
  1783 + \item If $A$ has priority $50$ and $B$ has priority $49$, $B$ runs $6,25$ percent slower than $A$.
1597 \end{liste} 1784 \end{liste}
1598 -\item We have several processes $A_1,\dots,A_k$ with priority level 100, and several processes $B_1,\dots,B_n$ with priority  
1599 - level 20. No $B$ process is running if at least one $A$ process is running. $B$ processes share the computation power  
1600 - if no $A$ process is running. 1785 +\item We have several processes $A_1,\dots,A_k$ with priority level $100$, and several processes $B_1,\dots,B_n$ with priority
  1786 + level $50$. No $B$ process is running if at least one $A$ process is running. $B$ processes share the computation power
  1787 + when no $A$ process is running.
1601 \item We can imagine a web site with absolutely prioritary processes (for administration), client processes (servicing web pages), 1788 \item We can imagine a web site with absolutely prioritary processes (for administration), client processes (servicing web pages),
1602 - and background task processes. The priorities could be set like this~: 20 for administration, 10 for clients, and 0 for the  
1603 - background. You can also imagine to put some administration task at the level 25. 1789 + and background task processes. The priorities could be set like this~: 50 for administration, 30 for clients, and 0 for the
  1790 + background.
1604 \end{liste} 1791 \end{liste}
  1792 +When anbexec starts, it runs a single process (the father of all processes). It has priority level~$255$.
1605 1793
1606 -When anbexec starts, it runs a single process (the father of all processes). It has priority 255, and you can change this priority  
1607 -at the beginning of your program if needed.  
1608 1794
1609 -  
1610 -%  
1611 -%  
1612 -%  
1613 -%  
1614 -%  
1615 -%  
1616 -%  
1617 -%  
1618 -%  
1619 -%  
1620 -%  
1621 -\subsubsection{Changing the priority level of a process}  
1622 -In order to change the priority level of a process, you need to be allowed to do so. The rules are~:  
1623 -\begin{liste}  
1624 -\item (1) A process can never have a priority level greater than its original priority level (the level it has when  
1625 - it was launched).  
1626 -\item (2) A process cannot launch a process with a priority level higher than its own priority level.  
1627 -\item (3) A process can change its own priority level.  
1628 -\item (4) A process having access to a datum of type \code{Process} can change the priority level of the process  
1629 - represented by this datum.  
1630 -\end{liste}  
1631 -Remark that the only possibility to obtain a datum of type \code{Process} is to launch a process with \code{delegate},  
1632 -or to get it through the following tool (defined in \code{predefined.anubis})~:  
1633 -{\color{darkblue}  
1634 -\begin{verbatim}  
1635 -public define Process my_process.  
1636 -\end{verbatim}  
1637 -}  
1638 -If a process executes \code{my\_process}, it gets its own process identifier.  
1639 1795
1640 -Getting and setting the priority level of a process is achieved by~:  
1641 -{\color{darkblue}  
1642 -\begin{verbatim}  
1643 -public define Word8 priority (Process p).  
1644 -public define One set_priority (Process p, Word8 level).  
1645 -\end{verbatim}  
1646 -} 1796 +\section{Anubis internals}
1647 1797
1648 -For example, if a process wants at some time to run in the background, it can execute~:  
1649 -\begin{center}  
1650 -\code{set\_priority(my\_process,0)}  
1651 -\end{center}  
1652 -If later it needs to come back to its original priority level, it can execute~:  
1653 -\begin{center}  
1654 -\code{set\_priority(my\_process,255)}  
1655 -\end{center}  
1656 -The function \code{set\_priority} will put its priority level at its original value (which may be different from~255). 1798 +\subsection{The garbage-collector}
1657 1799
1658 1800
1659 1801
anubis_dev/vm/src/AnubisProcess.cpp
@@ -71,9 +71,13 @@ AnubisProcess::~AnubisProcess(void) @@ -71,9 +71,13 @@ AnubisProcess::~AnubisProcess(void)
71 } 71 }
72 72
73 //int AnubisProcess::Create(int starting_point, U8 *byte_code, U32 code_size, AnubisAllocator *allocator) 73 //int AnubisProcess::Create(int starting_point, U8 *byte_code, U32 code_size, AnubisAllocator *allocator)
74 -int AnubisProcess::Create(U8 * starting_IP, AnubisAllocator *allocator) 74 +int AnubisProcess::Create(U8 * starting_IP, U8 priority, AnubisAllocator *allocator)
75 { 75 {
76 /* retuns -1 if no machine available, the machine id otherwise. */ 76 /* retuns -1 if no machine available, the machine id otherwise. */
  77 +
  78 + m_priority = priority;
  79 +
  80 + //printf("created process with priority %d\n",m_priority); fflush(stdout);
77 81
78 /* a machine has been found */ 82 /* a machine has been found */
79 /* give a stack to the machine */ 83 /* give a stack to the machine */
@@ -328,14 +332,14 @@ AnubisProcessList::AnubisProcessList() : @@ -328,14 +332,14 @@ AnubisProcessList::AnubisProcessList() :
328 } 332 }
329 333
330 //AnubisProcess * AnubisProcessList::CreateAnubisProcess(U32 starting_point, U8 *byte_code, U32 code_size, CM::AnubisAllocator * allocator) 334 //AnubisProcess * AnubisProcessList::CreateAnubisProcess(U32 starting_point, U8 *byte_code, U32 code_size, CM::AnubisAllocator * allocator)
331 -AnubisProcess * AnubisProcessList::CreateAnubisProcess(U8 * starting_IP, CM::AnubisAllocator * allocator) 335 +AnubisProcess * AnubisProcessList::CreateAnubisProcess(U8 * starting_IP, U8 priority, CM::AnubisAllocator * allocator)
332 { 336 {
333 AnubisProcess * processItem = new AnubisProcess(); 337 AnubisProcess * processItem = new AnubisProcess();
334 int pResult; //result status of the create 338 int pResult; //result status of the create
335 339
336 if (processItem) 340 if (processItem)
337 { 341 {
338 - pResult = processItem->Create(starting_IP, allocator); 342 + pResult = processItem->Create(starting_IP, priority, allocator);
339 if (pResult >= 0) 343 if (pResult >= 0)
340 { 344 {
341 AddItem(processItem); 345 AddItem(processItem);
anubis_dev/vm/src/AnubisProcess.h
@@ -60,7 +60,7 @@ class AnubisProcess @@ -60,7 +60,7 @@ class AnubisProcess
60 * @param allocator 60 * @param allocator
61 * @return Return the process id of new created process, otherwise -1 for error 61 * @return Return the process id of new created process, otherwise -1 for error
62 */ 62 */
63 - int Create(U8 * starting_IP, AnubisAllocator *allocator); 63 + int Create(U8 * starting_IP, U8 priority, AnubisAllocator *allocator);
64 64
65 /** 65 /**
66 * Set the pid of the process. usually is the process list who decide the pid of the 66 * Set the pid of the process. usually is the process list who decide the pid of the
@@ -121,7 +121,7 @@ class AnubisProcess @@ -121,7 +121,7 @@ class AnubisProcess
121 protected: 121 protected:
122 private: 122 private:
123 U32 m_pid; /* process unique id */ 123 U32 m_pid; /* process unique id */
124 - anbStatus m_status; /* current status of virtual machine */ 124 + anbStatus m_status; /* current status of this process */
125 U32 m_work_sort; /* what it is currently doing */ 125 U32 m_work_sort; /* what it is currently doing */
126 int m_steps; /* must be signed (((m_steps--) <= 0) in 'vm.cpp') */ 126 int m_steps; /* must be signed (((m_steps--) <= 0) in 'vm.cpp') */
127 U32 m_R; /* main register of the machine */ 127 U32 m_R; /* main register of the machine */
@@ -130,9 +130,9 @@ class AnubisProcess @@ -130,9 +130,9 @@ class AnubisProcess
130 //U32 m_starting_point; /* keep trace of starting point for debugging purpose.*/ 130 //U32 m_starting_point; /* keep trace of starting point for debugging purpose.*/
131 U8* m_IP; /* instruction pointer */ 131 U8* m_IP; /* instruction pointer */
132 U8* m_previous_IP; /* previous value of instruction pointer */ 132 U8* m_previous_IP; /* previous value of instruction pointer */
133 - U32 * m_SP_begin; /* address of machine's stack */ 133 + U32 * m_SP_begin; /* address of process stack */
134 U32 * m_SP; /* stack pointer */ 134 U32 * m_SP; /* stack pointer */
135 - U32 * m_SP_end; /* end of machine's stack */ 135 + U32 * m_SP_end; /* end of process stack */
136 /* the two fields below droped since version 1.13. They are incompatible with the loading 136 /* the two fields below droped since version 1.13. They are incompatible with the loading
137 of several modules, because the same process may execute code from different modules. 137 of several modules, because the same process may execute code from different modules.
138 (the same is true of 'm_starting_point' above) */ 138 (the same is true of 'm_starting_point' above) */
@@ -154,7 +154,7 @@ class AnubisProcess @@ -154,7 +154,7 @@ class AnubisProcess
154 // U32 m_locked_files_stack_size; /* current size of locked files stack */ 154 // U32 m_locked_files_stack_size; /* current size of locked files stack */
155 // U32 m_locked_files_SP; /* locked files stack pointer */ 155 // U32 m_locked_files_SP; /* locked files stack pointer */
156 // U32 * m_locked_files; /* stack of locked files (vm strings) */ 156 // U32 * m_locked_files; /* stack of locked files (vm strings) */
157 - U8 m_priority; //priority of the process 157 + U8 m_priority; // current priority of the process
158 #ifdef instruction_count 158 #ifdef instruction_count
159 U32 m_i_count[256]; /* one counter for each instruction */ 159 U32 m_i_count[256]; /* one counter for each instruction */
160 #endif 160 #endif
@@ -290,7 +290,7 @@ class AnubisProcessList : public List @@ -290,7 +290,7 @@ class AnubisProcessList : public List
290 static AnubisProcessList* GetInstance(); 290 static AnubisProcessList* GetInstance();
291 AnubisProcess * GetProcessAt(U32); 291 AnubisProcess * GetProcessAt(U32);
292 AnubisProcess * GetProcessByID(U32); 292 AnubisProcess * GetProcessByID(U32);
293 - AnubisProcess * CreateAnubisProcess(U8 * starting_IP, AnubisAllocator* allocator); 293 + AnubisProcess * CreateAnubisProcess(U8 * starting_IP, U8 priority, AnubisAllocator* allocator);
294 void DeleteProcess(U32 pid); 294 void DeleteProcess(U32 pid);
295 AnubisProcess * GetRunningProcess() const { return _runningProcess; } 295 AnubisProcess * GetRunningProcess() const { return _runningProcess; }
296 void SetRunningProcess(AnubisProcess * current) { _runningProcess = current; } 296 void SetRunningProcess(AnubisProcess * current) { _runningProcess = current; }
anubis_dev/vm/src/anbexec.cpp
@@ -713,8 +713,62 @@ static void calc_load(U32 ticks, U32 active_tasks /* fixed-point */, bigtime_t * @@ -713,8 +713,62 @@ static void calc_load(U32 ticks, U32 active_tasks /* fixed-point */, bigtime_t *
713 } 713 }
714 } 714 }
715 715
  716 +/* Computing the maximum of the priority levels of all running (non sleeping) machines */
  717 +static U8 max_priority_of_runnings(void)
  718 +{
  719 + U32 i;
  720 + U8 result = 0;
  721 + U8 p;
  722 + AnubisProcess * processItem;
  723 + U32 nbProcess = TheAnubisProcessList->GetCount();
  724 + for (i = nbProcess - 1; i != ~(U32)0; i--) // i-- with i unsigned and i = 0 is 111111111...1111 = ~0
  725 + {
  726 + processItem = TheAnubisProcessList->GetProcessAt(i);
  727 + if (!processItem) continue;
  728 + TheAnubisProcessList->SetRunningProcess(processItem);
  729 + AnubisProcess::anbStatus st = processItem->GetStatus();
  730 + p = processItem->GetPriority();
  731 + switch (st)
  732 + {
  733 + case AnubisProcess::running:
  734 + case AnubisProcess::waiting_for_event:
  735 + case AnubisProcess::waiting_for_condition: // machine in a 'wait for' loop
  736 + case AnubisProcess::waiting_for_completion: // of a child process ('execute')
  737 + result = sup(p,result);
  738 + break;
  739 +
  740 + default:
  741 + break;
  742 + }
  743 + }
  744 + return result;
  745 +}
716 746
717 747
  748 +/* computing the credit for running a machine */
  749 +static U32 compute_credit(U8 M, /* maximum of credit of all running machines */
  750 + U8 L) /* priority of the machine */
  751 +{
  752 + /* the formula for M - 16 < L < M:
  753 + M - L
  754 + result = D(1 - -----) = ((D<<4) - D(M-L))>>4
  755 + 16
  756 +
  757 + where D = default maximal credit (max_steps)
  758 + M = max priority of running processes
  759 + L = priority of process
  760 + */
  761 +#define D (max_steps)
  762 + int32 result;
  763 + do {
  764 + if (L >= M) result = max_steps;
  765 + else if (L <= (M - 16)) result = 0;
  766 + else result = ((D<<4) - D*(M-L))>>4;
  767 + } while(0);
  768 +#undef D
  769 + return (U32)result;
  770 +}
  771 +
718 772
719 /* The scheduler */ 773 /* The scheduler */
720 void schedul(void) 774 void schedul(void)
@@ -723,6 +777,7 @@ void schedul(void) @@ -723,6 +777,7 @@ void schedul(void)
723 U32 running_machines; 777 U32 running_machines;
724 U32 waiting_machines; 778 U32 waiting_machines;
725 U32 waiting_for_completion_machines; 779 U32 waiting_for_completion_machines;
  780 + U32 max_running_priority; /* the maximum of the priority levels of all running (non sleeping) machines */
726 U32 steps = 0; 781 U32 steps = 0;
727 U32 activity = 0; 782 U32 activity = 0;
728 U32 wmm, wsm, maf; 783 U32 wmm, wsm, maf;
@@ -770,6 +825,8 @@ void schedul(void) @@ -770,6 +825,8 @@ void schedul(void)
770 steps = 0; 825 steps = 0;
771 U32 nbProcess = TheAnubisProcessList->GetCount(); 826 U32 nbProcess = TheAnubisProcessList->GetCount();
772 AnubisProcess * processItem; 827 AnubisProcess * processItem;
  828 +
  829 + max_running_priority = max_priority_of_runnings();
773 830
774 //for (i = nbProcess - 1; i >= 0; i--) 831 //for (i = nbProcess - 1; i >= 0; i--)
775 for (i = nbProcess - 1; i != ~(U32)0; i--) // i-- with i unsigned and i = 0 is 111111111...1111 = ~0 832 for (i = nbProcess - 1; i != ~(U32)0; i--) // i-- with i unsigned and i = 0 is 111111111...1111 = ~0
@@ -794,13 +851,20 @@ void schedul(void) @@ -794,13 +851,20 @@ void schedul(void)
794 case CM::AnubisProcess::machine_not_used: 851 case CM::AnubisProcess::machine_not_used:
795 break; 852 break;
796 853
797 - case AnubisProcess::running:  
798 - steps = processItem->RunMachine(max_steps) ; 854 + case AnubisProcess::running:
  855 +#if 0
  856 + { /* debugging tool */
  857 + U8 p = processItem->GetPriority();
  858 + U32 c = compute_credit(max_running_priority,p);
  859 + if (p != 255) { printf("<%d|%d>",p,c); fflush(stdout); }
  860 + }
  861 +#endif
  862 + steps = processItem->RunMachine(compute_credit(max_running_priority,processItem->GetPriority())) ;
799 break; 863 break;
800 864
801 case AnubisProcess::waiting_for_event: 865 case AnubisProcess::waiting_for_event:
802 processItem->SetStatus(AnubisProcess::running); 866 processItem->SetStatus(AnubisProcess::running);
803 - steps = processItem->RunMachine(max_steps); 867 + steps = processItem->RunMachine(compute_credit(max_running_priority,processItem->GetPriority()));
804 break; 868 break;
805 869
806 case AnubisProcess::waiting_for_condition: // machine in a 'wait for' loop 870 case AnubisProcess::waiting_for_condition: // machine in a 'wait for' loop
@@ -808,12 +872,12 @@ void schedul(void) @@ -808,12 +872,12 @@ void schedul(void)
808 if (timevalless(processItem->GetAlarm(),&current_time)) 872 if (timevalless(processItem->GetAlarm(),&current_time))
809 { 873 {
810 processItem->SetStatus(AnubisProcess::running); 874 processItem->SetStatus(AnubisProcess::running);
811 - steps = processItem->RunMachine(max_steps); 875 + steps = processItem->RunMachine(compute_credit(max_running_priority,processItem->GetPriority()));
812 } 876 }
813 break; 877 break;
814 878
815 case AnubisProcess::waiting_for_completion: // of a child process ('execute') 879 case AnubisProcess::waiting_for_completion: // of a child process ('execute')
816 - steps = processItem->RunMachine(max_steps); 880 + steps = processItem->RunMachine(compute_credit(max_running_priority,processItem->GetPriority()));
817 break; 881 break;
818 882
819 case AnubisProcess::need_bigger_stack: 883 case AnubisProcess::need_bigger_stack:
@@ -1011,7 +1075,7 @@ void schedul(void) @@ -1011,7 +1075,7 @@ void schedul(void)
1011 { 1075 {
1012 //LOGERROR("CRITICAL ERROR: Main VM select() failed with error [%d].\n", LAST_SOCKET_ERROR); 1076 //LOGERROR("CRITICAL ERROR: Main VM select() failed with error [%d].\n", LAST_SOCKET_ERROR);
1013 usleep(1000); // this will ensure that we won't take all the CPU time if a socket is 1077 usleep(1000); // this will ensure that we won't take all the CPU time if a socket is
1014 - // invalid (bug encountered on 2007-08-15 by CR) 1078 + // invalid (bug encountered on 2007-08-15 by CR)
1015 } 1079 }
1016 #else 1080 #else
1017 // select(FD_SETSIZE,&rfds,NULL,NULL,alarm_set ? (&time_to_wait) : NULL); 1081 // select(FD_SETSIZE,&rfds,NULL,NULL,alarm_set ? (&time_to_wait) : NULL);
@@ -1597,6 +1661,7 @@ int main(int argc, char **argv) @@ -1597,6 +1661,7 @@ int main(int argc, char **argv)
1597 AnubisProcess * currentProcess; 1661 AnubisProcess * currentProcess;
1598 /* create a new Anubis Process, the first one. */ 1662 /* create a new Anubis Process, the first one. */
1599 currentProcess = TheAnubisProcessList->CreateAnubisProcess((the_primary_module.byte_code)+8+(the_primary_module.starting_point), 1663 currentProcess = TheAnubisProcessList->CreateAnubisProcess((the_primary_module.byte_code)+8+(the_primary_module.starting_point),
  1664 + 255, /* priority of 'mother' process */
1600 TheAnubisAllocator); 1665 TheAnubisAllocator);
1601 1666
1602 1667
anubis_dev/vm/src/vm.cpp
@@ -5754,7 +5754,70 @@ ci_decl(start) @@ -5754,7 +5754,70 @@ ci_decl(start)
5754 5754
5755 AnubisProcess * newProcess; 5755 AnubisProcess * newProcess;
5756 newProcess = TheAnubisProcessList-> 5756 newProcess = TheAnubisProcessList->
5757 - CreateAnubisProcess(MAM(m_IP)+6, /* new machine starting point */ 5757 + CreateAnubisProcess(MAM(m_IP)+6, /* new machine starting point (6 is the size of the 'start' instruction) */
  5758 + MAM(m_priority), /* priority level of current process */
  5759 + MAM(m_allocator));
  5760 +
  5761 + //printf("[%d] Creating new process. Starting %d. PID = %d\n", MAM(m_pid), relative_IP(MAM(m_IP)+6), newProcess->GetPid());
  5762 + if (!newProcess)
  5763 + /* cannot start a new machine yet, retry at next run */
  5764 + {
  5765 + MAM(m_steps) = 0;
  5766 + return;
  5767 + }
  5768 +
  5769 + /* the new machine has been started */
  5770 +#ifndef normal_machine
  5771 +#undef MAM(m_SP_begin)
  5772 +#endif
  5773 + new_stack = newProcess->GetSPBegin();
  5774 +#ifndef normal_machine
  5775 +#define MAM(m_SP_begin) (MAM(m_SP_begin))
  5776 +#endif
  5777 + new_stack[0] = 0; /* last return */
  5778 + for (i = d; i >= 1; i--)
  5779 + new_stack[d-i+1] = *(MAM(m_SP)-i);
  5780 +
  5781 +#ifndef normal_machine
  5782 +#undef MAM(m_SP)
  5783 +#endif
  5784 + newProcess->SetSP(new_stack + d + 1);
  5785 +#ifndef normal_machine
  5786 +#define MAM(m_SP) (MAM(m_SP))
  5787 +#endif
  5788 +
  5789 + MAM(m_IP) = (U8 *)get32(2);
  5790 +}
  5791 +
  5792 +
  5793 +
  5794 +
  5795 +/* Format: startp (U8)depth (U32)addr
  5796 +Size: 6
  5797 +
  5798 +This instruction starts a new virtual machine. The 'depth' argument is the number of
  5799 +items which should be copied from the top of the stack of the current machine, to the
  5800 +stack of the new machine. These items are just words. There is no virtual copy to
  5801 +perform. They have been already done by the instructions just before 'start'.
  5802 +
  5803 +The priority level (a Word8) is in R.
  5804 +
  5805 +'addr' is the address to which the current machine should jump after starting the new
  5806 +machine. The new machine itself executes the code following this 'start'
  5807 +instruction.
  5808 +
  5809 + */
  5810 +ci_decl(startp)
  5811 +{
  5812 + trace
  5813 + U32 *new_stack = NULL;
  5814 + U8 d = get8(1);
  5815 + U8 i;
  5816 +
  5817 + AnubisProcess * newProcess;
  5818 + newProcess = TheAnubisProcessList->
  5819 + CreateAnubisProcess(MAM(m_IP)+6, /* new machine starting point (6 is the size of the 'start' instruction) */
  5820 + MAM(m_R), /* priority level of new process */
5758 MAM(m_allocator)); 5821 MAM(m_allocator));
5759 5822
5760 //printf("[%d] Creating new process. Starting %d. PID = %d\n", MAM(m_pid), relative_IP(MAM(m_IP)+6), newProcess->GetPid()); 5823 //printf("[%d] Creating new process. Starting %d. PID = %d\n", MAM(m_pid), relative_IP(MAM(m_IP)+6), newProcess->GetPid());
anubis_dev/vm/src/vm.h
@@ -216,7 +216,7 @@ extern void serialize_float(double d, U8 *dest); @@ -216,7 +216,7 @@ extern void serialize_float(double d, U8 *dest);
216 struct Exec_Mod_struct { 216 struct Exec_Mod_struct {
217 U32 flags; /* also indicates is primary or secondary ('mf_secondary_adm' in 'bytecode.h') */ 217 U32 flags; /* also indicates is primary or secondary ('mf_secondary_adm' in 'bytecode.h') */
218 //U32 code_size; 218 //U32 code_size;
219 - /* since version 1.13, the 'byte_code' field does not only contain only the code. 219 + /* since version 1.13, the 'byte_code' field does not contain only the code.
220 It is an actual byte array, i.e. has the following form: 220 It is an actual byte array, i.e. has the following form:
221 221
222 +---------+---------+------------------------------------------- 222 +---------+---------+-------------------------------------------
@@ -224,7 +224,7 @@ struct Exec_Mod_struct { @@ -224,7 +224,7 @@ struct Exec_Mod_struct {
224 +---------+---------+------------------------------------------- 224 +---------+---------+-------------------------------------------
225 0 4 8 225 0 4 8
226 226
227 - This byte array contains its own size. This why the field 'code_size' has been removed. 227 + This byte array contains its own size. This is why the field 'code_size' has been removed.
228 228
229 An array of Exec_Mod_struct (see dynamic_module.cpp) contains all currently loaded modules. 229 An array of Exec_Mod_struct (see dynamic_module.cpp) contains all currently loaded modules.
230 Only the primary module is permanent, hence has its counter 'cnt' always at 0. 230 Only the primary module is permanent, hence has its counter 'cnt' always at 0.
anubis_dev/vm/src/vmtools.cpp
@@ -1013,6 +1013,7 @@ void link_globals_and_relocate(U8* code, @@ -1013,6 +1013,7 @@ void link_globals_and_relocate(U8* code,
1013 case i_mvar_slots_del_mixed: 1013 case i_mvar_slots_del_mixed:
1014 case i_indirect_del_mixed: 1014 case i_indirect_del_mixed:
1015 case i_start: 1015 case i_start:
  1016 + case i_startp:
1016 case i_type_mixed: 1017 case i_type_mixed:
1017 case i_indirect_type_mixed: 1018 case i_indirect_type_mixed:
1018 if (nsc_file != NULL) 1019 if (nsc_file != NULL)
anubis_distrib/linux_install/prepare_package/Makefile
1 1
2 -minnum = 13  
3 -relnum = 5 2 +minnum = 14
  3 +relnum = 0
4 bldnum = 0 4 bldnum = 0
5 5
6 package: 6 package: