> +int odph_odpthreads_create(odph_odpthread_t *thread_tbl,
> +                        const odp_cpumask_t *mask,
> +                        const odph_odpthread_params_t *thr_params)
> +{
> +     int i;
> +     int num;
> +     int cpu_count;
> +     int cpu;
> +
> +     num = odp_cpumask_count(mask);
> +
> +     memset(thread_tbl, 0, num * sizeof(odph_odpthread_t));
> +
> +     cpu_count = odp_cpu_count();
> +
> +     if (num < 1 || num > cpu_count) {
> +             ODPH_ERR("Invalid number of odpthreads:%d"
> +                      " (%d cores available)\n",
> +                      num, cpu_count);
> +             return -1;
> +     }
> +
> +     cpu = odp_cpumask_first(mask);
> +     for (i = 0; i < num; i++) {
> +             /*
> +              * Thread mode by default, or if both thread and proc mode
> +              * are required each second odpthread is a linux thread.
> +              */

This is a weird logic. All threads should be one type (when you have boolean 
cmd line params for thread type). Pthread should be the default, so all threads 
are pthreads if user don't give any param. It's an error if user gives both.

This follows a requirement from you that the linux ODP implementation should 
support a mix of both ODP threads implemented as pthread and process at the 
same time. I felt that a "--odph_mixed" option is not more clear than 
specifying both the things we want, i.e. processes and thread.
Any better suggestion?

You’d need more detailed information (than Boolean) for that advanced use case. 
At this point, all pthreads or all processes is sufficient for odp-linux. I 
have not required implementation of thread/process mix, but required that ODP 
API does not prevent different threading models.

Create all threads by default, all processes if helper_options.proc is true and 
report error is both are true.

if (helper_options.proc && helper_options.thrd)
              return -1;

if (helper_options.proc) {
              odph_linux_process_create();
} else {
              odph_linux_thread_create();
}






> +             if ((!helper_options.proc) ||
> +                 (helper_options.proc && helper_options.thrd && (i & 1))) {
> +                     if (odph_linux_thread_create(&thread_tbl[i],
> +                                                  cpu,
> +                                                  thr_params))
> +                             break;
> +              } else {
> +                     if (odph_linux_process_create(&thread_tbl[i],
> +                                                   cpu,
> +                                                   thr_params))
> +                             break;
> +             }
> +
> +             cpu = odp_cpumask_next(mask, cpu);
> +     }
> +     thread_tbl[num - 1].last = 1;
> +
> +     return i;
> +}
> +
> +/*
> + * wait for the odpthreads termination (linux processes and threads)
> + */
> +int odph_odpthreads_join(odph_odpthread_t *thread_tbl)
> +{
> +     pid_t pid;
> +     int i = 0;
> +     int terminated = 0;
> +     int status = 0;         /* child process return code (!=0 is error)
> */
> +     void *thread_ret;       /* "child" thread return code (NULL is error) */
> +     int ret;
> +     int retval = 0;
> +
> +     /* joins linux threads or wait for processes */
> +     do {
> +             /* pthreads: */
> +             switch (thread_tbl[i].start_args.linuxtype) {
> +             case ODPTHREAD_PTHREAD:
> +                     /* Wait thread to exit */
> +                     ret = pthread_join(thread_tbl[i].thread.thread_id,
> +                                        &thread_ret);
> +                     if (ret != 0) {
> +                             ODPH_ERR("Failed to join thread from cpu #%d\n",
> +                                      thread_tbl[i].cpu);
> +                             retval = -1;
> +                     } else {
> +                             terminated++;
> +                             if (thread_ret != NULL)
> +                                     retval = -1;
> +                     }
> +                     pthread_attr_destroy(&thread_tbl[i].thread.attr);
> +                     break;
> +
> +             case ODPTHREAD_PROCESS:
> +
> +                     /* processes: */
> +                     pid = waitpid(thread_tbl[i].proc.pid, &status, 0);
> +
> +                     if (pid < 0) {
> +                             ODPH_ERR("waitpid() failed\n");
> +                             retval = -1;
> +                             break;
> +                     }
> +
> +                     terminated++;
> +
> +                     /* Examine the child process' termination status */
> +                     if (WIFEXITED(status) &&
> +                         WEXITSTATUS(status) != EXIT_SUCCESS) {
> +                             ODPH_ERR("Child exit status:%d (pid:%d)\n",
> +                                      WEXITSTATUS(status), (int)pid);
> +                             retval = -1;
> +                     }
> +                     if (WIFSIGNALED(status)) {
> +                             int signo = WTERMSIG(status);
> +
> +                             ODPH_ERR("Child term signo:%d - %s (pid:%d)\n",
> +                                      signo, strsignal(signo), (int)pid);
> +                             retval = -1;
> +                     }
> +                     break;
> +
> +             case ODPTHREAD_NOT_STARTED:
> +                     ODPH_DBG("No join done on not started ODPthread.\n");
> +                     break;
> +             default:
> +                     ODPH_DBG("Invalid case statement value!\n");
> +                     break;
> +             }
> +
> +     } while (!thread_tbl[i++].last);
> +
> +     return (retval < 0) ? retval : terminated;
> +}
> +
> +/*
>   * Parse command line options to extract options affecting helpers.
>   */
>  int odph_parse_options(int argc, char *argv[])
> @@ -247,9 +508,15 @@ int odph_parse_options(int argc, char *argv[])
>
>       static struct option long_options[] = {
>               /* These options set a flag. */
> +             {"odph_proc",   no_argument, &helper_options.proc, 1},
> +             {"odph_thread", no_argument, &helper_options.thrd, 1},
>               {0, 0, 0, 0}
>               };
>
> +     /* defaults: */
> +     helper_options.proc = false;
> +     helper_options.thrd = false;

Pthread should be the default option. We should not always require a cmd line 
param from user (if no param ==> pthread).

We don't!. This structure reflects the options that getopts finds on the 
command line: Before parsing the command line, no options have been found!. The 
default IS pthread when no options are given.

Christophe.

Code would be more readable if global variables and their default values 
indicate what happens by default. Optimally, a number of  threads could be 
created even without calling the parse function (with empty argv). I think the 
helper documentation does not require that odph_parse_options() is called 
before calling odph_odpthreads_create(), or does it (in some of the patches).

-Petri





-Petri




> +
>       while (1) {
>               /* getopt_long stores the option index here. */
>               int option_index = 0;
> --
> 2.5.0
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org<mailto:lng-odp@lists.linaro.org>
> https://lists.linaro.org/mailman/listinfo/lng-odp

_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to