Changeset 1802 for trunk/src/kmk


Ignore:
Timestamp:
Sep 21, 2008, 8:40:44 PM (17 years ago)
Author:
bird
Message:

incdep: An experiment in pushing all the work to the threads.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/incdep.c

    r1801 r1802  
    3030*   Header Files                                                               *
    3131*******************************************************************************/
     32/*#define PARSE_IN_WORKER*/
     33
    3234#ifdef __OS2__
    3335# define INCL_BASE
     
    7880*   Structures and Typedefs                                                    *
    7981*******************************************************************************/
     82
     83struct incdep_variable_in_set
     84{
     85    struct incdep_variable_in_set *next;
     86    /* the parameters */
     87    char *name;                     /* xmalloc'ed -> strcache */
     88    unsigned int name_length;
     89    const char *value;              /* xmalloc'ed */
     90    unsigned int value_length;
     91    int duplicate_value;            /* 0 */
     92    enum variable_origin origin;
     93    int recursive;
     94    struct variable_set *set;
     95    const struct floc *flocp;       /* NILF */
     96};
     97
     98struct incdep_variable_def
     99{
     100    struct incdep_variable_def *next;
     101    /* the parameters */
     102    const struct floc *flocp;       /* NILF */
     103    char *name;                     /* xmalloc'ed -> strcache */
     104    unsigned int name_length;       /* (not an actual parameter) */
     105    char *value;                    /* xmalloc'ed, free it */
     106    enum variable_origin origin;
     107    enum variable_flavor flavor;
     108    int target_var;
     109};
     110
     111struct incdep_recorded_files
     112{
     113    struct incdep_recorded_files *next;
     114
     115    /* the parameters */
     116    struct nameseq *filenames;      /* only one file? its name needs be strcache'ed */
     117    const char *pattern;            /* NULL */
     118    const char *pattern_percent;    /* NULL */
     119    struct dep *deps;               /* names need to be strcache'ed */
     120    unsigned int cmds_started;      /* 0 */
     121    char *commands;                 /* NULL */
     122    unsigned int commands_idx;      /* 0 */
     123    int two_colon;                  /* 0 */
     124    const struct floc *flocp;       /* NILF */
     125};
     126
     127
    80128/* per dep file structure. */
    81129struct incdep
     
    84132  char *file_base;
    85133  char *file_end;
     134
     135  int is_worker;
     136#ifdef PARSE_IN_WORKER
     137  unsigned int err_line_no;
     138  const char *err_msg;
     139
     140  struct incdep_variable_in_set *recorded_variables_in_set_head;
     141  struct incdep_variable_in_set *recorded_variables_in_set_tail;
     142
     143  struct incdep_variable_def *recorded_variable_defs_head;
     144  struct incdep_variable_def *recorded_variable_defs_tail;
     145
     146  struct incdep_recorded_files *recorded_files_head;
     147  struct incdep_recorded_files *recorded_files_tail;
     148#endif
     149
    86150  char name[1];
    87151};
     
    146210*******************************************************************************/
    147211static void incdep_flush_it (struct floc *);
     212static void eval_include_dep_file (struct incdep *, struct floc *, int);
    148213
    149214
     
    301366  cur->file_base = cur->file_end = NULL;
    302367  return -1;
     368}
     369
     370/* Free the incdep structure. */
     371static void
     372incdep_free (struct incdep *cur)
     373{
     374#ifdef PARSE_IN_WORKER
     375  assert (!cur->recorded_variables_in_set_head);
     376  assert (!cur->recorded_variable_defs_head);
     377  assert (!cur->recorded_files_head);
     378#endif
     379
     380  free (cur->file_base);
     381  free (cur);
    303382}
    304383
     
    329408      incdep_unlock ();
    330409      incdep_read_file (cur, NILF);
     410#ifdef PARSE_IN_WORKER
     411      eval_include_dep_file (cur, NILF, 1 /* is_worker */);
     412#endif
    331413      incdep_lock ();
    332414
     
    506588}
    507589
    508 /* A quick wrapper around strcache_add_len which avoid the unnecessary
    509    copying of the string in order to terminate it. The incdep buffer is
    510    always writable, but the eval function like to use const char to avoid
    511    silly mistakes and encourage compiler optimizations. */
    512 static char *
    513 incdep_strcache_add_len (const char *str, int len)
    514 {
    515 #if 1
    516   char *ret;
    517   char ch = str[len];
    518   ((char *)str)[len] = '\0';
    519   ret = strcache_add_len (str, len);
    520   ((char *)str)[len] = ch;
     590#ifdef PARSE_IN_WORKER
     591/* Flushes the recorded instructions. */
     592static void
     593incdep_flush_recorded_instructions (struct incdep *cur)
     594{
     595  struct incdep_variable_in_set *rec_vis;
     596  struct incdep_variable_def *rec_vd;
     597  struct incdep_recorded_files *rec_f;
     598
     599  /* define_variable_in_set */
     600
     601  rec_vis = cur->recorded_variables_in_set_head;
     602  cur->recorded_variables_in_set_head = cur->recorded_variables_in_set_tail = NULL;
     603  if (rec_vis)
     604    do
     605      {
     606        void *free_me = rec_vis;
     607        define_variable_in_set (strcache_add_len (rec_vis->name, rec_vis->name_length),
     608                                rec_vis->name_length,
     609                                rec_vis->value,
     610                                rec_vis->value_length,
     611                                rec_vis->duplicate_value,
     612                                rec_vis->origin,
     613                                rec_vis->recursive,
     614                                rec_vis->set,
     615                                rec_vis->flocp);
     616        free (rec_vis->name);
     617        rec_vis = rec_vis->next;
     618        free (free_me);
     619      }
     620    while (rec_vis);
     621
     622  /* do_variable_definition */
     623
     624  rec_vd = cur->recorded_variable_defs_head;
     625  cur->recorded_variable_defs_head = cur->recorded_variable_defs_tail = NULL;
     626  if (rec_vd)
     627    do
     628      {
     629        void *free_me = rec_vd;
     630        do_variable_definition (rec_vd->flocp,
     631                                strcache_add_len(rec_vd->name, rec_vd->name_length),
     632                                rec_vd->value,
     633                                rec_vd->origin,
     634                                rec_vd->flavor,
     635                                rec_vd->target_var);
     636        free (rec_vd->name);
     637        free (rec_vd->value);
     638        rec_vd = rec_vd->next;
     639        free (free_me);
     640      }
     641    while (rec_vd);
     642
     643  /* record_files */
     644
     645  rec_f = cur->recorded_files_head;
     646  cur->recorded_files_head = cur->recorded_files_tail = NULL;
     647  if (rec_f)
     648    do
     649      {
     650        void *free_me = rec_f;
     651        struct dep *dep;
     652        const char *newname;
     653
     654        for (dep = rec_f->deps; dep; dep = dep->next)
     655          {
     656            newname = strcache_add (dep->name);
     657            free ((char *)dep->name);
     658            dep->name = newname;
     659          }
     660
     661        newname = strcache_add (rec_f->filenames->name);
     662        free ((char *)rec_f->filenames->name);
     663        rec_f->filenames->name = newname;
     664
     665        record_files (rec_f->filenames,
     666                      rec_f->pattern,
     667                      rec_f->pattern_percent,
     668                      rec_f->deps,
     669                      rec_f->cmds_started,
     670                      rec_f->commands,
     671                      rec_f->commands_idx,
     672                      rec_f->two_colon,
     673                      rec_f->flocp);
     674
     675        rec_f = rec_f->next;
     676        free (free_me);
     677      }
     678    while (rec_f);
     679}
     680#endif /* PARSE_IN_WORKER */
     681
     682/* Record / issue a warning about a misformed dep file. */
     683static void
     684incdep_warn (struct incdep *cur, unsigned int line_no, const char *msg)
     685{
     686  if (!cur->is_worker)
     687    error (NILF, "%s(%d): %s", cur->name, line_no, msg);
     688#ifdef PARSE_IN_WORKER
     689  else
     690    {
     691      cur->err_line_no = line_no;
     692      cur->err_msg = msg;
     693    }
     694#endif
     695}
     696
     697/* Record / execute a strcache add. */
     698static const char *
     699incdep_record_strcache (struct incdep *cur, const char *str, int len)
     700{
     701  const char *ret;
     702  if (!cur->is_worker)
     703    {
     704      /* Make sure the string is terminated before we hand it to
     705         strcache_add_len so it does have to make a temporary copy
     706         of it on the stack. */
     707      char ch = str[len];
     708      ((char *)str)[len] = '\0';
     709      ret = strcache_add_len (str, len);
     710      ((char *)str)[len] = ch;
     711    }
     712  else
     713    {
     714      /* Duplicate the string. The other recorders knows which arguments
     715         needs to be added to the string cache later. */
     716      char *newstr = xmalloc (len + 1);
     717      memcpy (newstr, str, len);
     718      newstr[len] = '\0';
     719      ret = newstr;
     720    }
    521721  return ret;
    522 #else
    523   return strcache_add_len (str, len);
    524 #endif
    525 }
     722}
     723
     724/* Record / perform a variable definition in a set.
     725   The NAME is in the string cache.
     726   The VALUE is on the heap.
     727   The DUPLICATE_VALUE is always 0. */
     728static void
     729incdep_record_variable_in_set (struct incdep *cur,
     730                               const char *name, unsigned int name_length,
     731                               const char *value,
     732                               unsigned int value_length,
     733                               int duplicate_value,
     734                               enum variable_origin origin,
     735                               int recursive,
     736                               struct variable_set *set,
     737                               const struct floc *flocp)
     738{
     739  assert (!duplicate_value);
     740  if (!cur->is_worker)
     741    define_variable_in_set (name, name_length, value, value_length,
     742                            duplicate_value, origin, recursive, set, flocp);
     743#ifdef PARSE_IN_WORKER
     744  else
     745    {
     746      struct incdep_variable_in_set *rec = xmalloc (sizeof (*rec));
     747      rec->name = (char *)name;
     748      rec->name_length = name_length;
     749      rec->value = value;
     750      rec->value_length = value_length;
     751      rec->duplicate_value = duplicate_value;
     752      rec->origin = origin;
     753      rec->recursive = recursive;
     754      rec->set = set;
     755      rec->flocp = flocp;
     756
     757      rec->next = NULL;
     758      if (cur->recorded_variables_in_set_tail)
     759        cur->recorded_variables_in_set_tail->next = rec;
     760      else
     761        cur->recorded_variables_in_set_head = rec;
     762      cur->recorded_variables_in_set_tail = rec;
     763    }
     764#endif
     765}
     766
     767/* Record / perform a variable definition. The VALUE should be disposed of. */
     768static void
     769incdep_record_variable_def (struct incdep *cur,
     770                            const struct floc *flocp,
     771                            const char *name,
     772                            unsigned int name_length,
     773                            char *value,
     774                            enum variable_origin origin,
     775                            enum variable_flavor flavor,
     776                            int target_var)
     777{
     778  if (!cur->is_worker)
     779    {
     780      do_variable_definition (flocp, name, value, origin, flavor, target_var);
     781      free (value);
     782    }
     783#ifdef PARSE_IN_WORKER
     784  else
     785    {
     786      struct incdep_variable_def *rec = xmalloc (sizeof (*rec));
     787      rec->flocp = flocp;
     788      rec->name = (char *)name;
     789      rec->name_length = name_length;
     790      rec->value = value;
     791      rec->origin = origin;
     792      rec->flavor = flavor;
     793      rec->target_var = target_var;
     794
     795      rec->next = NULL;
     796      if (cur->recorded_variable_defs_tail)
     797        cur->recorded_variable_defs_tail->next = rec;
     798      else
     799        cur->recorded_variable_defs_head = rec;
     800      cur->recorded_variable_defs_tail = rec;
     801    }
     802#endif
     803}
     804
     805/* Record files.*/
     806static void
     807incdep_record_files (struct incdep *cur,
     808                     struct nameseq *filenames, const char *pattern,
     809                     const char *pattern_percent, struct dep *deps,
     810                     unsigned int cmds_started, char *commands,
     811                     unsigned int commands_idx, int two_colon,
     812                     const struct floc *flocp)
     813{
     814  if (!cur->is_worker)
     815    record_files (filenames, pattern, pattern_percent, deps, cmds_started,
     816                  commands, commands_idx, two_colon, flocp);
     817#ifdef PARSE_IN_WORKER
     818  else
     819    {
     820      struct incdep_recorded_files *rec = xmalloc (sizeof (*rec));
     821
     822      rec->filenames = filenames;
     823      rec->pattern = pattern;
     824      rec->pattern_percent = pattern_percent;
     825      rec->deps = deps;
     826      rec->cmds_started = cmds_started;
     827      rec->commands = commands;
     828      rec->commands_idx = commands_idx;
     829      rec->two_colon = two_colon;
     830      rec->flocp = flocp;
     831
     832      rec->next = NULL;
     833      if (cur->recorded_files_tail)
     834        cur->recorded_files_tail->next = rec;
     835      else
     836        cur->recorded_files_head = rec;
     837      cur->recorded_files_tail = rec;
     838    }
     839#endif
     840}
     841
    526842
    527843/* no nonsense dependency file including.
     
    545861   */
    546862static void
    547 eval_include_dep_file (struct incdep *curdep, struct floc *f)
     863eval_include_dep_file (struct incdep *curdep, struct floc *f, int is_worker)
    548864{
    549865  unsigned line_no = 1;
     
    554870  /* if no file data, just return immediately. */
    555871  if (!cur)
    556     {
    557       free (curdep);
    558       return;
    559     }
     872    return;
     873  curdep->is_worker = is_worker;
    560874
    561875  /* now parse the file. */
     
    617931          if (!var_len)
    618932          {
    619               error (f, "%s(%d): bogus define statement.",
    620                      curdep->name, line_no);
     933              incdep_warn (curdep, line_no, "bogus define statement.");
    621934              break;
    622935          }
    623           var = incdep_strcache_add_len (cur, var_len);
     936          var = incdep_record_strcache (curdep, cur, var_len);
    624937
    625938          /* find the end of the variable. */
     
    654967          if (!found_endef)
    655968            {
    656               error (f, "%s(%d): missing endef, dropping the rest of the file.",
    657                      curdep->name, line_no);
     969              incdep_warn (curdep, line_no, "missing endef, dropping the rest of the file.");
    658970              break;
    659971            }
     
    661973          if (memchr (value_start, '\0', value_len))
    662974            {
    663               error (f, "%s(%d): '\\0' in define, dropping the rest of the file.",
    664                      curdep->name, line_no);
     975              incdep_warn (curdep, line_no, "'\\0' in define, dropping the rest of the file.");
    665976              break;
    666977            }
     
    6931004          value [value_len] = '\0';
    6941005
    695           define_variable_in_set (var, var_len, value, value_len,
    696                                   0 /* don't duplicate */, o_file,
    697                                   0 /* defines are recursive but this is faster */,
    698                                   NULL /* global set */, f);
     1006          incdep_record_variable_in_set (curdep,
     1007                                         var, var_len, value, value_len,
     1008                                         0 /* don't duplicate */, o_file,
     1009                                         0 /* defines are recursive but this is faster */,
     1010                                         NULL /* global set */, f);
    6991011        }
    7001012
     
    7301042                  || (!endp && memchr (cur, '\n', equalp - cur)))
    7311043                {
    732                   error (f, "%s(%d): no colon.",
    733                          curdep->name, line_no);
     1044                  incdep_warn (curdep, line_no, "no colon.");
    7341045                  break;
    7351046                }
     
    7711082              if (!var_len)
    7721083                {
    773                   error (f, "%s(%d): empty variable. (includedep)",
    774                          curdep->name, line_no);
     1084                  incdep_warn (curdep, line_no, "empty variable. (includedep)");
    7751085                  break;
    7761086                }
     
    7791089                  || memchr (cur, '\t', var_len))
    7801090                {
    781                   error (f, "%s(%d): fancy variable name. (includedep)",
    782                          curdep->name, line_no);
     1091                  incdep_warn (curdep, line_no, "fancy variable name. (includedep)");
    7831092                  break;
    7841093                }
    785               var = incdep_strcache_add_len (cur, var_len);
     1094              var = incdep_record_strcache (curdep, cur, var_len);
    7861095
    7871096              /* find the start of the value. */
     
    8081117                  if (value_end - 1 >= cur && value_end[-1] == '\\')
    8091118                    {
    810                       error (f, "%s(%d): fancy escaping! (includedep)",
    811                              curdep->name, line_no);
     1119                      incdep_warn (curdep, line_no, "fancy escaping! (includedep)");
    8121120                      cur = NULL;
    8131121                      break;
     
    8651173               || (   flavor == f_simple
    8661174                   && !memchr (value, '$', value_len)))
    867                 define_variable_in_set (var, var_len, value, value_len,
    868                                         0 /* don't duplicate */, o_file,
    869                                         flavor == f_recursive /* recursive */,
    870                                         NULL /* global set */, f);
     1175                incdep_record_variable_in_set (curdep,
     1176                                               var, var_len, value, value_len,
     1177                                               0 /* don't duplicate */, o_file,
     1178                                               flavor == f_recursive /* recursive */,
     1179                                               NULL /* global set */, f);
    8711180              else
    872                 {
    873                   do_variable_definition (f, var, value, o_file, flavor,
    874                                           0 /* not target var */);
    875                   free (value);
    876                 }
     1181                incdep_record_variable_def (curdep,
     1182                                            f, var, var_len, value, o_file, flavor,
     1183                                            0 /* not target var */);
    8771184            }
    8781185          else
     
    8841191              struct dep **nextdep = &deps;
    8851192              struct dep *dep;
    886 /*              int next_line = 1; */
    8871193
    8881194              /* extract the filename, ASSUME a single one. */
     
    8921198              if (cur == endp)
    8931199                {
    894                   error (f, "%s(%d): empty filename.",
    895                          curdep->name, line_no);
     1200                  incdep_warn (curdep, line_no, "empty filename.");
    8961201                  break;
    8971202                }
     
    9001205                  || memchr (cur, '\t', endp - cur))
    9011206                {
    902                   error (f, "%s(%d): multiple / fancy file name. (includedep)",
    903                          curdep->name, line_no);
     1207                  incdep_warn (curdep, line_no, "multiple / fancy file name. (includedep)");
    9041208                  break;
    9051209                }
    9061210              filenames = xmalloc (sizeof (struct nameseq));
    9071211              memset (filenames, 0, sizeof (*filenames));
    908               filenames->name = incdep_strcache_add_len (cur, endp - cur);
     1212              filenames->name = incdep_record_strcache (curdep, cur, endp - cur);
    9091213
    9101214              /* parse any dependencies. */
     
    9451249                  /* add it to the list. */
    9461250                  *nextdep = dep = alloc_dep ();
    947                   dep->name = incdep_strcache_add_len (cur, endp - cur);
     1251                  dep->name = incdep_record_strcache (curdep, cur, endp - cur);
    9481252                  nextdep = &dep->next;
    9491253
     
    9521256
    9531257              /* enter the file with its dependencies. */
    954               record_files (filenames, NULL, NULL, deps, 0, NULL, 0, 0, f);
     1258              incdep_record_files (curdep,
     1259                                   filenames, NULL, NULL, deps, 0, NULL, 0, 0, f);
    9551260            }
    9561261        }
    9571262    }
    9581263
    959   free (curdep->file_base);
    960   free (curdep);
     1264  /* free the file data */
     1265  if (is_worker)
     1266    {
     1267      free (curdep->file_base);
     1268      curdep->file_base = curdep->file_end = NULL;
     1269    }
    9611270}
    9621271
     
    9811290
    9821291          incdep_read_file (cur, f);
    983           eval_include_dep_file (cur, f); /* eats cur */
     1292          eval_include_dep_file (cur, f, 0);
     1293          incdep_free (cur);
    9841294
    9851295          incdep_lock ();
     
    10051315        {
    10061316          struct incdep *next = cur->next;
    1007           eval_include_dep_file (cur, f); /* eats cur */
     1317#ifdef PARSE_IN_WORKER
     1318          incdep_flush_recorded_instructions (cur);
     1319#else
     1320          eval_include_dep_file (cur, f, 0);
     1321#endif
     1322          incdep_free (cur);
    10081323          cur = next;
    10091324        }
     
    10351350       memcpy (cur->name, name, name_len);
    10361351       cur->name[name_len] = '\0';
     1352       cur->is_worker = 0;
     1353#ifdef PARSE_IN_WORKER
     1354       cur->err_line_no = 0;
     1355       cur->err_msg = NULL;
     1356       cur->recorded_variables_in_set_head = NULL;
     1357       cur->recorded_variables_in_set_tail = NULL;
     1358       cur->recorded_variable_defs_head = NULL;
     1359       cur->recorded_variable_defs_tail = NULL;
     1360       cur->recorded_files_head = NULL;
     1361       cur->recorded_files_tail = NULL;
     1362#endif
    10371363
    10381364       cur->next = NULL;
     
    10531379          struct incdep *next = cur->next;
    10541380          incdep_read_file (cur, f);
    1055           eval_include_dep_file (cur, f); /* eats cur */
     1381          eval_include_dep_file (cur, f, 0); /* eats cur */
    10561382          cur = next;
    10571383        }
Note: See TracChangeset for help on using the changeset viewer.