Sorry for not testing this earlier, but while this works fine on 64-bit
systems, it fails to compile on 32-bit systems:

  CC       odp_traffic_mngr.lo
odp_traffic_mngr.c: In function ‘_odp_tm_group_create’:
odp_traffic_mngr.c:2646:9: error: cast from pointer to integer of different
size [-Werror=pointer-to-int-cast]
  return (_odp_tm_group_t)tm_group;
         ^
odp_traffic_mngr.c: In function ‘_odp_tm_group_destroy’:
odp_traffic_mngr.c:2654:13: error: cast to pointer from integer of
different size [-Werror=int-to-pointer-cast]
  tm_group = (tm_system_group_t *)odp_tm_group;
             ^
odp_traffic_mngr.c: In function ‘_odp_tm_group_add’:
odp_traffic_mngr.c:2688:14: error: cast to pointer from integer of
different size [-Werror=int-to-pointer-cast]
  tm_group  = (tm_system_group_t *)odp_tm_group;
              ^
odp_traffic_mngr.c: In function ‘_odp_tm_group_remove’:
odp_traffic_mngr.c:2723:14: error: cast to pointer from integer of
different size [-Werror=int-to-pointer-cast]
  tm_group  = (tm_system_group_t *)odp_tm_group;
              ^
odp_traffic_mngr.c: In function ‘tm_group_attach’:
odp_traffic_mngr.c:2772:18: error: cast from pointer to integer of
different size [-Werror=pointer-to-int-cast]
   odp_tm_group = (_odp_tm_group_t)tm_group;
                  ^
odp_traffic_mngr.c:2803:17: error: cast from pointer to integer of
different size [-Werror=pointer-to-int-cast]
  odp_tm_group = (_odp_tm_group_t)tm_group;
                 ^
cc1: all warnings being treated as errors
Makefile:850: recipe for target 'odp_traffic_mngr.lo' failed
make[1]: *** [odp_traffic_mngr.lo] Error 1


On Sun, Aug 7, 2016 at 9:45 PM, Barry Spinney <spin...@mellanox.com> wrote:

> These changes add a new concept called the tm_system_group.  This new
> entity collects together a set of tm_systems that all share some
> common resources - eg. share the service thread.
>
> Signed-off-by: Barry Spinney <spin...@mellanox.com>
> ---
>  .../include/odp_traffic_mngr_internal.h            |  34 ++-
>  platform/linux-generic/odp_traffic_mngr.c          | 233
> +++++++++++++++++++--
>  2 files changed, 249 insertions(+), 18 deletions(-)
>
> diff --git a/platform/linux-generic/include/odp_traffic_mngr_internal.h
> b/platform/linux-generic/include/odp_traffic_mngr_internal.h
> index e4bc5ce..3d8328e 100644
> --- a/platform/linux-generic/include/odp_traffic_mngr_internal.h
> +++ b/platform/linux-generic/include/odp_traffic_mngr_internal.h
> @@ -347,14 +347,25 @@ typedef struct {
>         tm_tos_marking_t  ip_tos_marking[ODP_NUM_PACKET_COLORS];
>  } tm_marking_t;
>
> -typedef struct {
> +typedef struct tm_system_s       tm_system_t;
> +typedef struct tm_system_group_s tm_system_group_t;
> +typedef        uint64_t          _odp_tm_group_t;
> +
> +struct tm_system_s {
> +       /* The previous and next tm_system in the same tm_system_group.
> These
> +        * links form a circle and so to round robin amongst the
> tm_system's
> +        * one just needs to continue to follow next. In the case where the
> +        * tm_system_group only has one tm_system, the prev and next point
> to
> +        * this single tm_system. */
> +       tm_system_t    *prev;
> +       tm_system_t    *next;
> +       _odp_tm_group_t odp_tm_group;
> +
>         odp_ticketlock_t tm_system_lock;
>         odp_barrier_t    tm_system_barrier;
>         odp_barrier_t    tm_system_destroy_barrier;
>         odp_atomic_u64_t destroying;
>         _odp_int_name_t  name_tbl_id;
> -       pthread_t        thread;
> -       pthread_attr_t   attr;
>
>         void               *trace_buffer;
>         uint32_t            next_queue_num;
> @@ -389,7 +400,22 @@ typedef struct {
>         uint64_t shaper_green_cnt;
>         uint64_t shaper_yellow_cnt;
>         uint64_t shaper_red_cnt;
> -} tm_system_t;
> +};
> +
> +/* A tm_system_group is a set of 1 to N tm_systems that share some
> processing
> + * resources - like a bunch of service threads, input queue, timers, etc.
> + * Currently a tm_system_group only supports a single service thread - and
> + * while the input work queue is shared - timers are not. */
> +
> +struct tm_system_group_s {
> +       tm_system_group_t *prev;
> +       tm_system_group_t *next;
> +
> +       tm_system_t   *first_tm_system;
> +       uint32_t       num_tm_systems;
> +       pthread_t      thread;
> +       pthread_attr_t attr;
> +};
>
>  #ifdef __cplusplus
>  }
> diff --git a/platform/linux-generic/odp_traffic_mngr.c
> b/platform/linux-generic/odp_traffic_mngr.c
> index 1e302f9..5dc1033 100644
> --- a/platform/linux-generic/odp_traffic_mngr.c
> +++ b/platform/linux-generic/odp_traffic_mngr.c
> @@ -78,11 +78,14 @@ static dynamic_tbl_t odp_tm_profile_tbls[ODP_TM_
> NUM_PROFILES];
>  /* TM systems table. */
>  static tm_system_t *odp_tm_systems[ODP_TM_MAX_NUM_SYSTEMS];
>
> +static tm_system_group_t *tm_group_list;
> +
>  static odp_ticketlock_t tm_create_lock;
>  static odp_ticketlock_t tm_profile_lock;
>  static odp_barrier_t tm_first_enq;
>
>  static int g_main_thread_cpu = -1;
> +static int g_tm_cpu_num;
>
>  /* Forward function declarations. */
>  static void tm_queue_cnts_decrement(tm_system_t *tm_system,
> @@ -2312,6 +2315,7 @@ static void *tm_system_thread(void *arg)
>  {
>         _odp_timer_wheel_t _odp_int_timer_wheel;
>         input_work_queue_t *input_work_queue;
> +       tm_system_group_t  *tm_group;
>         tm_system_t *tm_system;
>         uint64_t current_ns;
>         uint32_t destroying, work_queue_cnt, timer_cnt;
> @@ -2319,7 +2323,9 @@ static void *tm_system_thread(void *arg)
>
>         rc = odp_init_local(INSTANCE_ID, ODP_THREAD_WORKER);
>         ODP_ASSERT(rc == 0);
> -       tm_system = arg;
> +       tm_group = arg;
> +
> +       tm_system = tm_group->first_tm_system;
>         _odp_int_timer_wheel = tm_system->_odp_int_timer_wheel;
>         input_work_queue = tm_system->input_work_queue;
>
> @@ -2371,6 +2377,11 @@ static void *tm_system_thread(void *arg)
>                 tm_system->is_idle = (timer_cnt == 0) &&
>                         (work_queue_cnt == 0);
>                 destroying = odp_atomic_load_u64(&tm_system->destroying);
> +
> +               /* Advance to the next tm_system in the tm_system_group. */
> +               tm_system = tm_system->next;
> +               _odp_int_timer_wheel = tm_system->_odp_int_timer_wheel;
> +               input_work_queue = tm_system->input_work_queue;
>         }
>
>         odp_barrier_wait(&tm_system->tm_system_destroy_barrier);
> @@ -2558,7 +2569,7 @@ static int affinitize_main_thread(void)
>  static uint32_t tm_thread_cpu_select(void)
>  {
>         odp_cpumask_t odp_cpu_mask;
> -       int           cpu_count;
> +       int           cpu_count, cpu;
>
>         odp_cpumask_default_worker(&odp_cpu_mask, 0);
>         if ((g_main_thread_cpu != -1) &&
> @@ -2576,30 +2587,224 @@ static uint32_t tm_thread_cpu_select(void)
>                         odp_cpumask_all_available(&odp_cpu_mask);
>         }
>
> -       return odp_cpumask_first(&odp_cpu_mask);
> +       if (g_tm_cpu_num == 0) {
> +               cpu = odp_cpumask_first(&odp_cpu_mask);
> +       } else {
> +               cpu = odp_cpumask_next(&odp_cpu_mask, g_tm_cpu_num);
> +               if (cpu == -1) {
> +                       g_tm_cpu_num = 0;
> +                       cpu = odp_cpumask_first(&odp_cpu_mask);
> +               }
> +       }
> +
> +       g_tm_cpu_num++;
> +       return cpu;
>  }
>
> -static int tm_thread_create(tm_system_t *tm_system)
> +static int tm_thread_create(tm_system_group_t *tm_group)
>  {
>         cpu_set_t      cpu_set;
>         uint32_t       cpu_num;
>         int            rc;
>
> -       pthread_attr_init(&tm_system->attr);
> +       pthread_attr_init(&tm_group->attr);
>         cpu_num = tm_thread_cpu_select();
>         CPU_ZERO(&cpu_set);
>         CPU_SET(cpu_num, &cpu_set);
> -       pthread_attr_setaffinity_np(&tm_system->attr, sizeof(cpu_set_t),
> +       pthread_attr_setaffinity_np(&tm_group->attr, sizeof(cpu_set_t),
>                                     &cpu_set);
>
> -       rc = pthread_create(&tm_system->thread, &tm_system->attr,
> -                           tm_system_thread, tm_system);
> +       rc = pthread_create(&tm_group->thread, &tm_group->attr,
> +                           tm_system_thread, tm_group);
>         if (rc != 0)
>                 ODP_DBG("Failed to start thread on cpu num=%u\n", cpu_num);
>
>         return rc;
>  }
>
> +static _odp_tm_group_t _odp_tm_group_create(const char *name ODP_UNUSED)
> +{
> +       tm_system_group_t *tm_group, *first_tm_group, *second_tm_group;
> +
> +       tm_group = malloc(sizeof(tm_system_group_t));
> +       memset(tm_group, 0, sizeof(tm_system_group_t));
> +
> +       /* Add this group to the tm_group_list linked list. */
> +       if (tm_group_list == NULL) {
> +               tm_group_list  = tm_group;
> +               tm_group->next = tm_group;
> +               tm_group->prev = tm_group;
> +       } else {
> +               first_tm_group        = tm_group_list;
> +               second_tm_group       = first_tm_group->next;
> +               first_tm_group->next  = tm_group;
> +               second_tm_group->prev = tm_group;
> +               tm_group->next        = second_tm_group;
> +               tm_group->prev        = first_tm_group;
> +       }
> +
> +       return (_odp_tm_group_t)tm_group;
> +}
> +
> +static void _odp_tm_group_destroy(_odp_tm_group_t odp_tm_group)
> +{
> +       tm_system_group_t *tm_group, *prev_tm_group, *next_tm_group;
> +       int                rc;
> +
> +       tm_group = (tm_system_group_t *)odp_tm_group;
> +
> +       /* Wait for the thread to exit. */
> +       ODP_ASSERT(tm_group->num_tm_systems <= 1);
> +       rc = pthread_join(tm_group->thread, NULL);
> +       ODP_ASSERT(rc == 0);
> +       pthread_attr_destroy(&tm_group->attr);
> +       if (g_tm_cpu_num > 0)
> +               g_tm_cpu_num--;
> +
> +       /* Remove this group from the tm_group_list linked list. Special
> case
> +        * when this is the last tm_group in the linked list. */
> +       prev_tm_group = tm_group->prev;
> +       next_tm_group = tm_group->next;
> +       if (prev_tm_group == next_tm_group) {
> +               ODP_ASSERT(tm_group_list == tm_group);
> +               tm_group_list = NULL;
> +       } else {
> +               prev_tm_group->next = next_tm_group;
> +               next_tm_group->prev = prev_tm_group;
> +               if (tm_group_list == tm_group)
> +                       tm_group_list = next_tm_group;
> +       }
> +
> +       tm_group->prev = NULL;
> +       tm_group->next = NULL;
> +       free(tm_group);
> +}
> +
> +static int _odp_tm_group_add(_odp_tm_group_t odp_tm_group, odp_tm_t
> odp_tm)
> +{
> +       tm_system_group_t *tm_group;
> +       tm_system_t       *tm_system, *first_tm_system, *second_tm_system;
> +
> +       tm_group  = (tm_system_group_t *)odp_tm_group;
> +       tm_system = GET_TM_SYSTEM(odp_tm);
> +       tm_group->num_tm_systems++;
> +       tm_system->odp_tm_group = odp_tm_group;
> +
> +       /* Link this tm_system into the circular linked list of all
> tm_systems
> +        * belonging to the same tm_group. */
> +       if (tm_group->num_tm_systems == 1) {
> +               tm_group->first_tm_system = tm_system;
> +               tm_system->next           = tm_system;
> +               tm_system->prev           = tm_system;
> +       } else {
> +               first_tm_system        = tm_group->first_tm_system;
> +               second_tm_system       = first_tm_system->next;
> +               first_tm_system->next  = tm_system;
> +               second_tm_system->prev = tm_system;
> +               tm_system->prev        = first_tm_system;
> +               tm_system->next        = second_tm_system;
> +               tm_group->first_tm_system = tm_system;
> +       }
> +
> +       /* If this is the first tm_system associated with this group, then
> +        * create the service thread and the input work queue. */
> +       if (tm_group->num_tm_systems >= 2)
> +               return 0;
> +
> +       affinitize_main_thread();
> +       return tm_thread_create(tm_group);
> +}
> +
> +static int _odp_tm_group_remove(_odp_tm_group_t odp_tm_group, odp_tm_t
> odp_tm)
> +{
> +       tm_system_group_t *tm_group;
> +       tm_system_t       *tm_system, *prev_tm_system, *next_tm_system;
> +
> +       tm_group  = (tm_system_group_t *)odp_tm_group;
> +       tm_system = GET_TM_SYSTEM(odp_tm);
> +       if (tm_system->odp_tm_group != odp_tm_group)
> +               return -1;
> +
> +       if ((tm_group->num_tm_systems  == 0) ||
> +           (tm_group->first_tm_system == NULL))
> +               return -1;
> +
> +       /* Remove this tm_system from the tm_group linked list. */
> +       if (tm_group->first_tm_system == tm_system)
> +               tm_group->first_tm_system = tm_system->next;
> +
> +       prev_tm_system       = tm_system->prev;
> +       next_tm_system       = tm_system->next;
> +       prev_tm_system->next = next_tm_system;
> +       next_tm_system->prev = prev_tm_system;
> +       tm_system->next      = NULL;
> +       tm_system->prev      = NULL;
> +       tm_group->num_tm_systems--;
> +
> +       /* If this is the last tm_system associated with this group then
> +        * destroy the group (and thread etc). */
> +       if (tm_group->num_tm_systems == 0)
> +               _odp_tm_group_destroy(odp_tm_group);
> +
> +       return 0;
> +}
> +
> +static int tm_group_attach(odp_tm_t odp_tm)
> +{
> +       tm_system_group_t *tm_group, *min_tm_group;
> +       _odp_tm_group_t    odp_tm_group;
> +       odp_cpumask_t      all_cpus, worker_cpus;
> +       uint32_t           total_cpus, avail_cpus;
> +
> +       /* If this platform has a small number of cpu's then allocate one
> +        * tm_group and assign all tm_system's to this tm_group.
> Otherwise in
> +        * the case of a manycore platform try to allocate one tm_group per
> +        * tm_system, as long as there are still extra cpu's left.  If not
> +        * enough cpu's left than allocate this tm_system to the next
> tm_group
> +        * in a round robin fashion. */
> +       odp_cpumask_all_available(&all_cpus);
> +       odp_cpumask_default_worker(&worker_cpus, 0);
> +       total_cpus = odp_cpumask_count(&all_cpus);
> +       avail_cpus = odp_cpumask_count(&worker_cpus);
> +
> +       if (total_cpus < 24) {
> +               tm_group     = tm_group_list;
> +               odp_tm_group = (_odp_tm_group_t)tm_group;
> +               if (tm_group == NULL)
> +                       odp_tm_group = _odp_tm_group_create("");
> +
> +               _odp_tm_group_add(odp_tm_group, odp_tm);
> +               return 0;
> +       }
> +
> +       /* Manycore case. */
> +       if ((tm_group_list == NULL) || (avail_cpus > 1)) {
> +               odp_tm_group = _odp_tm_group_create("");
> +               _odp_tm_group_add(odp_tm_group, odp_tm);
> +               return 0;
> +       }
> +
> +       /* Pick a tm_group according to the smallest number of tm_systems.
> */
> +       tm_group     = tm_group_list;
> +       min_tm_group = NULL;
> +       while (tm_group != NULL) {
> +               if (min_tm_group == NULL)
> +                       min_tm_group = tm_group;
> +               else if (tm_group->num_tm_systems <
> +                        min_tm_group->num_tm_systems)
> +                       min_tm_group = tm_group;
> +
> +               tm_group = tm_group->next;
> +       }
> +
> +       if (min_tm_group == NULL)
> +               return -1;
> +
> +       odp_tm_group = (_odp_tm_group_t)tm_group;
> +       _odp_tm_group_add(odp_tm_group, odp_tm);
> +       return 0;
> +}
> +
>  odp_tm_t odp_tm_create(const char            *name,
>                        odp_tm_requirements_t *requirements,
>                        odp_tm_egress_t       *egress)
> @@ -2697,8 +2902,9 @@ odp_tm_t odp_tm_create(const char            *name,
>         }
>
>         if (create_fail == 0) {
> +               /* Pass any odp_groups or hints to tm_group_attach here. */
>                 affinitize_main_thread();
> -               rc = tm_thread_create(tm_system);
> +               rc = tm_group_attach(odp_tm);
>                 create_fail |= rc < 0;
>         }
>
> @@ -2758,7 +2964,6 @@ int odp_tm_capability(odp_tm_t odp_tm,
> odp_tm_capabilities_t *capabilities)
>  int odp_tm_destroy(odp_tm_t odp_tm)
>  {
>         tm_system_t *tm_system;
> -       int rc;
>
>         tm_system = GET_TM_SYSTEM(odp_tm);
>
> @@ -2769,10 +2974,10 @@ int odp_tm_destroy(odp_tm_t odp_tm)
>         odp_atomic_inc_u64(&tm_system->destroying);
>         odp_barrier_wait(&tm_system->tm_system_destroy_barrier);
>
> -       /* Next wait for the thread to exit. */
> -       rc = pthread_join(tm_system->thread, NULL);
> -       ODP_ASSERT(rc == 0);
> -       pthread_attr_destroy(&tm_system->attr);
> +       /* Remove ourselves from the group.  If we are the last tm_system
> in
> +        * this group, odp_tm_group_remove will destroy any service threads
> +        * allocated by this group. */
> +       _odp_tm_group_remove(tm_system->odp_tm_group, odp_tm);
>
>         input_work_queue_destroy(tm_system->input_work_queue);
>         _odp_sorted_pool_destroy(tm_system->_odp_int_sorted_pool);
> --
> 2.1.2
>
>

Reply via email to