"Fossies" - the Fresh Open Source Software Archive

Member "ponyc-0.33.2/src/libponyrt/sched/start.c" (3 Feb 2020, 9430 Bytes) of package /linux/misc/ponyc-0.33.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "start.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.33.1_vs_0.33.2.

    1 #define PONY_WANT_ATOMIC_DEFS
    2 
    3 #include "scheduler.h"
    4 #include "cpu.h"
    5 #include "../mem/heap.h"
    6 #include "../actor/actor.h"
    7 #include "../gc/cycle.h"
    8 #include "../gc/serialise.h"
    9 #include "../lang/process.h"
   10 #include "../lang/socket.h"
   11 #include "../options/options.h"
   12 #include "ponyassert.h"
   13 #include <dtrace.h>
   14 #include <string.h>
   15 #include <stdlib.h>
   16 #include <stdio.h>
   17 
   18 #ifdef USE_VALGRIND
   19 #include <valgrind/helgrind.h>
   20 #endif
   21 
   22 typedef struct options_t
   23 {
   24   // concurrent options
   25   uint32_t threads;
   26   uint32_t min_threads;
   27   bool noscale;
   28   uint32_t thread_suspend_threshold;
   29   uint32_t cd_detect_interval;
   30   size_t gc_initial;
   31   double gc_factor;
   32   bool noyield;
   33   bool noblock;
   34   bool pin;
   35   bool pinasio;
   36   bool version;
   37   bool ponyhelp;
   38 } options_t;
   39 
   40 typedef enum running_kind_t
   41 {
   42   NOT_RUNNING,
   43   RUNNING_DEFAULT,
   44   RUNNING_LIBRARY
   45 } running_kind_t;
   46 
   47 // global data
   48 static PONY_ATOMIC(bool) initialised;
   49 static PONY_ATOMIC(running_kind_t) running;
   50 static PONY_ATOMIC(int) rt_exit_code;
   51 
   52 static pony_language_features_init_t language_init;
   53 
   54 enum
   55 {
   56   OPT_MAXTHREADS,
   57   OPT_MINTHREADS,
   58   OPT_NOSCALE,
   59   OPT_SUSPENDTHRESHOLD,
   60   OPT_CDINTERVAL,
   61   OPT_GCINITIAL,
   62   OPT_GCFACTOR,
   63   OPT_NOYIELD,
   64   OPT_NOBLOCK,
   65   OPT_PIN,
   66   OPT_PINASIO,
   67   OPT_VERSION,
   68   OPT_PONYHELP
   69 };
   70 
   71 static opt_arg_t args[] =
   72 {
   73   {"ponymaxthreads", 0, OPT_ARG_REQUIRED, OPT_MAXTHREADS},
   74   {"ponyminthreads", 0, OPT_ARG_REQUIRED, OPT_MINTHREADS},
   75   {"ponynoscale", 0, OPT_ARG_NONE, OPT_NOSCALE},
   76   {"ponysuspendthreshold", 0, OPT_ARG_REQUIRED, OPT_SUSPENDTHRESHOLD},
   77   {"ponycdinterval", 0, OPT_ARG_REQUIRED, OPT_CDINTERVAL},
   78   {"ponygcinitial", 0, OPT_ARG_REQUIRED, OPT_GCINITIAL},
   79   {"ponygcfactor", 0, OPT_ARG_REQUIRED, OPT_GCFACTOR},
   80   {"ponynoyield", 0, OPT_ARG_NONE, OPT_NOYIELD},
   81   {"ponynoblock", 0, OPT_ARG_NONE, OPT_NOBLOCK},
   82   {"ponypin", 0, OPT_ARG_NONE, OPT_PIN},
   83   {"ponypinasio", 0, OPT_ARG_NONE, OPT_PINASIO},
   84   {"ponyversion", 0, OPT_ARG_NONE, OPT_VERSION},
   85   {"ponyhelp", 0, OPT_ARG_NONE, OPT_PONYHELP},
   86 
   87   OPT_ARGS_FINISH
   88 };
   89 
   90 #ifdef __cplusplus
   91 extern "C" {
   92 #endif
   93 void Main_runtime_override_defaults_oo(options_t* opt);
   94 #ifdef __cplusplus
   95 }
   96 #endif
   97 
   98 static const char* arg_name(const int id) {
   99   return args[id].long_opt;
  100 }
  101 
  102 static void err_out(int id, const char* msg) {
  103   printf("--%s %s\n", arg_name(id), msg);
  104   exit(255);
  105 }
  106 
  107 static int parse_uint(uint32_t* target, int min, const char *value) {
  108   int v = atoi(value);
  109   if (v < (min < 0 ? 0 : min)) {
  110     return 1;
  111   }
  112   *target = v;
  113   return 0;
  114 } 
  115 
  116 static int parse_size(size_t* target, int min, const char *value) {
  117   int v = atoi(value);
  118   if (v < (min < 0 ? 0 : min)) {
  119     return 1;
  120   }
  121   *target = v;
  122   return 0;
  123 } 
  124 
  125 static int parse_udouble(double* target, double min, const char *value) {
  126   double v = atof(value);
  127   if (v < (min < 0 ? 0 : min)) {
  128     return 1;
  129   }
  130   *target = v;
  131   return 0;
  132 } 
  133 
  134 static int parse_opts(int argc, char** argv, options_t* opt)
  135 {
  136   opt_state_t s;
  137   int id;
  138   ponyint_opt_init(args, &s, &argc, argv);
  139   bool minthreads_set = false;
  140 
  141   while((id = ponyint_opt_next(&s)) != -1)
  142   {
  143     switch(id)
  144     {
  145       case OPT_MAXTHREADS: if(parse_uint(&opt->threads, 1, s.arg_val)) err_out(id, "can't be less than 1"); break;
  146       case OPT_MINTHREADS: if(parse_uint(&opt->min_threads, 0, s.arg_val)) err_out(id, "can't be less than 0"); minthreads_set = true; break;
  147       case OPT_NOSCALE: opt->noscale= true; break;
  148       case OPT_SUSPENDTHRESHOLD: if(parse_uint(&opt->thread_suspend_threshold, 0, s.arg_val)) err_out(id, "can't be less than 0"); break;
  149       case OPT_CDINTERVAL: if(parse_uint(&opt->cd_detect_interval, 0, s.arg_val)) err_out(id, "can't be less than 0"); break;
  150       case OPT_GCINITIAL: if(parse_size(&opt->gc_initial, 0, s.arg_val)) err_out(id, "can't be less than 0"); break;
  151       case OPT_GCFACTOR: if(parse_udouble(&opt->gc_factor, 1.0, s.arg_val)) err_out(id, "can't be less than 1.0"); break;
  152       case OPT_NOYIELD: opt->noyield = true; break;
  153       case OPT_NOBLOCK: opt->noblock = true; break;
  154       case OPT_PIN: opt->pin = true; break;
  155       case OPT_PINASIO: opt->pinasio = true; break;
  156       case OPT_VERSION: opt->version = true; break;
  157       case OPT_PONYHELP: opt->ponyhelp = true; break;
  158 
  159       case -2:
  160         // an error message has been printed by ponyint_opt_next
  161         exit(-1);
  162         break;
  163 
  164       default:
  165         exit(-1);
  166         break;
  167     }
  168   }
  169 
  170   if (opt->noscale)
  171   {
  172     if (minthreads_set)
  173     {
  174       printf("--%s & --%s are mutually exclusive\n", arg_name(OPT_MINTHREADS), arg_name(OPT_NOSCALE));
  175       exit(-1);
  176     }
  177     opt->min_threads = opt->threads;
  178   }
  179 
  180   argv[argc] = NULL;
  181   return argc;
  182 }
  183 
  184 PONY_API int pony_init(int argc, char** argv)
  185 {
  186   bool prev_init = atomic_exchange_explicit(&initialised, true,
  187     memory_order_relaxed);
  188   (void)prev_init;
  189   pony_assert(!prev_init);
  190   pony_assert(
  191     atomic_load_explicit(&running, memory_order_relaxed) == NOT_RUNNING);
  192 
  193   atomic_thread_fence(memory_order_acquire);
  194 #ifdef USE_VALGRIND
  195   ANNOTATE_HAPPENS_AFTER(&initialised);
  196   ANNOTATE_HAPPENS_AFTER(&running);
  197 #endif
  198 
  199   DTRACE0(RT_INIT);
  200   options_t opt;
  201   memset(&opt, 0, sizeof(options_t));
  202 
  203   // Defaults.
  204   opt.min_threads = 0;
  205   opt.cd_detect_interval = 100;
  206   opt.gc_initial = 14;
  207   opt.gc_factor = 2.0f;
  208   opt.pin = false;
  209 
  210   pony_register_thread();
  211 
  212   // Allow override via bare function on Main actor
  213   Main_runtime_override_defaults_oo(&opt);
  214 
  215   argc = parse_opts(argc, argv, &opt);
  216 
  217   if (opt.ponyhelp) {
  218     printf("%s", PONYRT_HELP);
  219     exit(0);
  220   }
  221 
  222   if (opt.version) {
  223 #ifdef _MSC_VER
  224         printf("%s %d\n", PONY_VERSION_STR, _MSC_VER);
  225 #else
  226         printf("%s\n", PONY_VERSION_STR);
  227 #endif
  228     exit(0);
  229   }
  230 
  231   ponyint_cpu_init();
  232 
  233   if (opt.threads == 0) {
  234     opt.threads = ponyint_cpu_count();
  235   }
  236   else if (opt.threads > ponyint_cpu_count())
  237   {
  238     printf("Can't have --%s > physical cores, the number of threads you'd be running with (%u > %u)\n", arg_name(OPT_MAXTHREADS), opt.threads, ponyint_cpu_count());
  239     exit(-1);
  240   }
  241 
  242   if (opt.min_threads > opt.threads)
  243   {
  244     printf("Can't have --%s > --%s (%u > %u)\n", arg_name(OPT_MINTHREADS), arg_name(OPT_MAXTHREADS), opt.min_threads, opt.threads);
  245     exit(-1);
  246   }
  247 
  248   ponyint_heap_setinitialgc(opt.gc_initial);
  249   ponyint_heap_setnextgcfactor(opt.gc_factor);
  250   ponyint_actor_setnoblock(opt.noblock);
  251 
  252   pony_exitcode(0);
  253 
  254   pony_ctx_t* ctx = ponyint_sched_init(opt.threads, opt.noyield, opt.pin,
  255     opt.pinasio, opt.min_threads, opt.thread_suspend_threshold);
  256 
  257   ponyint_cycle_create(ctx, opt.cd_detect_interval);
  258 
  259   return argc;
  260 }
  261 
  262 PONY_API bool pony_start(bool library, int* exit_code,
  263   const pony_language_features_init_t* language_features)
  264 {
  265   pony_assert(atomic_load_explicit(&initialised, memory_order_relaxed));
  266 
  267   // Set to RUNNING_DEFAULT even if library is true so that pony_stop() isn't
  268   // callable until the runtime has actually started.
  269   running_kind_t prev_running = atomic_exchange_explicit(&running,
  270     RUNNING_DEFAULT, memory_order_relaxed);
  271   (void)prev_running;
  272   pony_assert(prev_running == NOT_RUNNING);
  273 
  274   if(language_features != NULL)
  275   {
  276     memcpy(&language_init, language_features,
  277       sizeof(pony_language_features_init_t));
  278 
  279     if(language_init.init_network && !ponyint_os_sockets_init())
  280     {
  281       atomic_store_explicit(&running, NOT_RUNNING, memory_order_relaxed);
  282       return false;
  283     }
  284 
  285     if(language_init.init_serialisation &&
  286       !ponyint_serialise_setup(language_init.descriptor_table,
  287         language_init.descriptor_table_size))
  288     {
  289       atomic_store_explicit(&running, NOT_RUNNING, memory_order_relaxed);
  290       return false;
  291     }
  292   } else {
  293     memset(&language_init, 0, sizeof(pony_language_features_init_t));
  294   }
  295 
  296   if(!ponyint_sched_start(library))
  297   {
  298     atomic_store_explicit(&running, NOT_RUNNING, memory_order_relaxed);
  299     return false;
  300   }
  301 
  302   if(library)
  303   {
  304 #ifdef USE_VALGRIND
  305     ANNOTATE_HAPPENS_BEFORE(&running);
  306 #endif
  307     atomic_store_explicit(&running, RUNNING_LIBRARY, memory_order_release);
  308     return true;
  309   }
  310 
  311   if(language_init.init_network)
  312     ponyint_os_sockets_final();
  313 
  314   int ec = pony_get_exitcode();
  315 #ifdef USE_VALGRIND
  316   ANNOTATE_HAPPENS_BEFORE(&initialised);
  317   ANNOTATE_HAPPENS_BEFORE(&running);
  318 #endif
  319   atomic_thread_fence(memory_order_acq_rel);
  320   atomic_store_explicit(&initialised, false, memory_order_relaxed);
  321   atomic_store_explicit(&running, NOT_RUNNING, memory_order_relaxed);
  322 
  323   if(exit_code != NULL)
  324     *exit_code = ec;
  325 
  326   return true;
  327 }
  328 
  329 PONY_API int pony_stop()
  330 {
  331   pony_assert(atomic_load_explicit(&initialised, memory_order_relaxed));
  332 
  333   running_kind_t loc_running = atomic_load_explicit(&running,
  334     memory_order_acquire);
  335 #ifdef USE_VALGRIND
  336   ANNOTATE_HAPPENS_AFTER(&running);
  337 #endif
  338   (void)loc_running;
  339   pony_assert(loc_running == RUNNING_LIBRARY);
  340 
  341   ponyint_sched_stop();
  342 
  343   if(language_init.init_network)
  344     ponyint_os_sockets_final();
  345 
  346   int ec = pony_get_exitcode();
  347 #ifdef USE_VALGRIND
  348   ANNOTATE_HAPPENS_BEFORE(&initialised);
  349   ANNOTATE_HAPPENS_BEFORE(&running);
  350 #endif
  351   atomic_thread_fence(memory_order_acq_rel);
  352   atomic_store_explicit(&initialised, false, memory_order_relaxed);
  353   atomic_store_explicit(&running, NOT_RUNNING, memory_order_relaxed);
  354   return ec;
  355 }
  356 
  357 PONY_API void pony_exitcode(int code)
  358 {
  359   atomic_store_explicit(&rt_exit_code, code, memory_order_relaxed);
  360 }
  361 
  362 PONY_API int pony_get_exitcode()
  363 {
  364   return atomic_load_explicit(&rt_exit_code, memory_order_relaxed);
  365 }