Motr  M0
processor.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/syscall.h> /* syscall, SYS_getcpu */
29 #include <dirent.h>
30 #include <unistd.h>
31 #include <linux/limits.h>
32 #include <sched.h> /* sched_getcpu() */
33 
34 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_OTHER
35 #include "lib/trace.h"
36 #include "lib/errno.h"
37 #include "lib/memory.h"
38 #include "lib/processor.h"
39 #include "lib/list.h"
40 #include "lib/thread.h"
41 #include "module/instance.h"
42 
71 #define PROCESSORS_INFO_ENV "M0_PROCESSORS_INFO_DIR"
72 
73 #define PROCESSORS_SYSFS_DIR "/sys/devices/system"
74 #define PROCESSORS_CPU_DIR "cpu/"
75 #define PROCESSORS_NODE_DIR "node/"
76 
77 #define PROCESSORS_MAX_FILE "cpu/kernel_max"
78 #define PROCESSORS_POSS_FILE "cpu/possible"
79 #define PROCESSORS_PRESENT_FILE "cpu/present"
80 #define PROCESSORS_ONLINE_FILE "cpu/online"
81 
82 #define PROCESSORS_CACHE1_LEVEL_FILE "cache/index0/level"
83 #define PROCESSORS_CACHE2_LEVEL_FILE "cache/index1/level"
84 #define PROCESSORS_CACHE3_LEVEL_FILE "cache/index2/level"
85 
86 #define PROCESSORS_CACHE1_SHCPUMAP_FILE "cache/index0/shared_cpu_map"
87 #define PROCESSORS_CACHE2_SHCPUMAP_FILE "cache/index1/shared_cpu_map"
88 #define PROCESSORS_CACHE3_SHCPUMAP_FILE "cache/index2/shared_cpu_map"
89 
90 #define PROCESSORS_CACHE1_SIZE_FILE "cache/index0/size"
91 #define PROCESSORS_CACHE2_SIZE_FILE "cache/index1/size"
92 #define PROCESSORS_CACHE3_SIZE_FILE "cache/index2/size"
93 
94 #define PROCESSORS_COREID_FILE "topology/core_id"
95 #define PROCESSORS_PHYSID_FILE "topology/physical_package_id"
96 
97 #define PROCESSORS_CPU_DIR_PREFIX "cpu/cpu"
98 
99 #define PROCESSORS_NODE_STR "node"
100 #define PROCESSORS_CPU_STR "cpu"
101 
102 enum {
105 
108 
110 };
111 
112 enum map {
116 };
117 
128 
132 
135 
138 
141 };
142 
151 
154 };
155 
166 };
167 
176 };
177 
178 /* Global Variables. */
180 static bool processor_init = false;
181 
193 static void processor_map_set(struct m0_bitmap *map, const char *mapstr)
194 {
195  uint32_t id;
196  uint32_t to_id;
197  char *ptr;
198 
199  M0_PRE(map != NULL);
200  M0_PRE(mapstr != NULL);
201 
202  /*
203  * Walk the string, parsing separate cpu ranges.
204  * For example, the string looks like 0-3,7,8-12
205  */
206  for (; mapstr != NULL && *mapstr != 0; mapstr = ptr) {
207  /*
208  * Parse from and to indices within the range.
209  */
210  id = strtoul(mapstr, &ptr, 0);
212  to_id = strtoul(ptr + 1, &ptr, 0);
213  else
214  to_id = id;
215  /*
216  * Set the bitmap for the given range.
217  */
218  M0_ASSERT(to_id < map->b_nr);
219  while (id <= to_id)
220  m0_bitmap_set(map, id++, true);
222  ++ptr;
223  else
224  ptr = NULL;
225  } /* for - string is parsed */
226 }
227 
236 {
237  int rc;
238  char buf[MAX_LINE_LEN + 1];
239  char *str;
240  FILE *fp;
241  struct m0_bitmap *pbitmap;
242  static const char *fname[] = {
246  };
247 
248  M0_PRE((unsigned) map_type <= PROCESSORS_ONLN_MAP);
249  fp = fopen(fname[map_type], "r");
250  if (fp == NULL)
251  return -errno;
252 
253  str = fgets(buf, MAX_LINE_LEN, fp);
254  fclose(fp);
255  if (str == NULL)
256  return M0_ERR(-ENODATA);
257 
258  switch (map_type) {
259  case PROCESSORS_POSS_MAP :
260  pbitmap = &sys_cpus.pss_poss_map;
261  break;
262 
263  case PROCESSORS_AVAIL_MAP :
264  pbitmap = &sys_cpus.pss_avail_map;
265  break;
266 
267  case PROCESSORS_ONLN_MAP :
268  pbitmap = &sys_cpus.pss_onln_map;
269  break;
270  default:
271  M0_IMPOSSIBLE("Incorrect map_type value");
272  pbitmap = NULL;
273  break;
274  }
275 
276  rc = m0_bitmap_init(pbitmap, sys_cpus.pss_max);
277  if (rc == 0)
278  processor_map_set(pbitmap, buf);
279  return M0_RC(rc);
280 }
281 
289 static uint32_t number_read(const char *filename)
290 {
291  uint32_t val = M0_PROCESSORS_INVALID_ID;
292  int rc;
293  FILE *fp;
294 
295  fp = fopen(filename, "r");
296  if (fp == NULL)
297  return val;
298 
299  rc = fscanf(fp, "%u", &val);
300  if (rc <= 0)
302 
303  fclose(fp);
304  return val;
305 }
306 
315 static void processor_maxsz_get()
316 {
317  /*
318  * cpu/kernel_max contains maximum index which starts from 0. Therefore,
319  * we need to convert it to maximum number of CPUs.
320  */
322 }
323 
333 {
334  uint32_t numa_node_id = 0;
335  bool gotid = false;
336  int rc;
337  char dirname[PATH_MAX];
338  DIR *dirp;
339  struct stat statbuf;
340  struct dirent *fname;
341 
342  sprintf(dirname, PROCESSORS_CPU_DIR_PREFIX"%u", id);
343  dirp = opendir(dirname);
344  if (dirp == NULL)
345  return numa_node_id;
346 
347  /*
348  * Find node id under .../cpu/cpu<id>/node<id>
349  */
350  while ((fname = readdir(dirp)) != NULL) {
351  if (strncmp(fname->d_name, PROCESSORS_NODE_STR,
352  sizeof(PROCESSORS_NODE_STR) - 1) == 0) {
353  sscanf(fname->d_name,
354  PROCESSORS_NODE_STR"%u", &numa_node_id);
355  gotid = true;
356  break;
357  }
358  }/* while - entire cpuX dir is scanned */
359 
360  closedir(dirp);
361  if (gotid)
362  return numa_node_id;
363 
364  /*
365  * If nodeid file is not found in previous search, look for cpuX file
366  * under node/nod<id>/cpu<id>
367  */
368  dirp = opendir(PROCESSORS_NODE_DIR);
369  if (dirp == NULL)
370  return numa_node_id;
371 
372  while ((fname = readdir(dirp)) != NULL) {
373  if (strncmp(fname->d_name, PROCESSORS_NODE_STR,
374  sizeof(PROCESSORS_NODE_STR) - 1) == 0) {
375  sprintf(dirname, "%s%s/%s%u",
376  PROCESSORS_NODE_DIR, fname->d_name,
377  PROCESSORS_CPU_STR, id);
378  rc = stat(dirname, &statbuf);
379  if (rc == 0) {
380  sscanf(fname->d_name,
381  PROCESSORS_NODE_STR"%u", &numa_node_id);
382  break;
383  }
384  }
385  }/* while - entire node dir is scanned */
386  closedir(dirp);
387 
388  /*
389  * Note : If no numa node id is found, it's assumed to be 0.
390  */
391  return numa_node_id;
392 }
393 
404 {
405  char filebuf[PATH_MAX];
406 
407  sprintf(filebuf, PROCESSORS_CPU_DIR_PREFIX"%u/"
409  return number_read(filebuf);
410 }
411 
422 {
423  char filebuf[PATH_MAX];
424 
425  sprintf(filebuf, PROCESSORS_CPU_DIR_PREFIX"%u/"
427  return number_read(filebuf);
428 }
429 
437 static bool processor_is_cache_shared(const char *mapstr)
438 {
439  char *ptr;
440  uint32_t num;
441  int shared_cpus = 0;
442 
443  /*
444  * The string is a bitmap. Each byte string is separated by ','.
445  */
446  for (; mapstr != NULL && *mapstr != 0; mapstr = ptr) {
447  /*
448  * Convert the "bytes" hexstring into a number, add to bits set.
449  */
450  for (num = strtoul(mapstr, &ptr, 16); num != 0; num >>= 1)
451  shared_cpus += num & 1;
452  /*
453  * If we have already found more than one cpu, don't
454  * scan further.
455  */
456  if (shared_cpus > 1) /* Is cache shared? */
457  break;
459  ++ptr;
460  else
461  ptr = NULL;
462  } /* for - entire string is parsed */
463 
464  M0_POST(shared_cpus >= 1);
465  return shared_cpus > 1;
466 }
467 
476 {
477  uint32_t level;
478  uint32_t sz;
479  int rc;
480  size_t size = 0;
481  char filename[PATH_MAX];
482  FILE *fp;
483 
484  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
488  return size;
489 
491 
492  /*
493  * Set path to appropriate cache size file
494  */
495  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
497 
498  /*
499  * Get the size string. It's in format 32K, 6144K etc.
500  */
501  fp = fopen(filename, "r");
502  if (fp == NULL)
503  return size;
504 
505  rc = fscanf(fp, "%uK", &sz);
506  fclose(fp);
507  if (rc <= 0)
508  return size;
509 
510  size = (size_t) sz * 1024;
511  return size;
512 }
513 
523 {
524  uint32_t level;
525  uint32_t sz;
526  int rc;
527  size_t size = 0;
528  char filename[PATH_MAX];
529  FILE *fp;
530 
531  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
535  return size;
536 
537  if (level != PROCESSORS_L2) { /* If L2 level is not found */
538  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
542  return size;
543 
545  /*
546  * Set path to appropriate cache size file
547  */
548  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
550  } else {
551  /*
552  * Set path to appropriate cache size file
553  */
554  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
556  }
557 
558  /*
559  * Get the size string. It's in format 32K, 6144K etc.
560  */
561  fp = fopen(filename, "r");
562  if (fp == NULL)
563  return size;
564 
565  rc = fscanf(fp, "%uK", &sz);
566  fclose(fp);
567  if (rc <= 0)
568  return size;
569 
570  size = (size_t)(sz * 1024);
571  return size;
572 }
573 
583 {
584  uint32_t level;
585  uint32_t coreid;
586  uint32_t physid;
587  uint32_t l1_id = id;
588 
589  bool is_shared;
590 
591  char filename[PATH_MAX];
592  char buf[MAX_LINE_LEN + 1];
593  char *str;
594 
595  FILE *fp;
596 
597  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
601  return l1_id;
602 
604  /*
605  * Set path to appropriate shared cpu file name
606  */
607  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
609 
610  /*
611  * Get the shared cpu map string.
612  */
613  fp = fopen(filename, "r");
614  if (fp == NULL)
615  return l1_id;
616 
617  str = fgets(buf, MAX_LINE_LEN, fp);
618  fclose(fp);
619  if (str == NULL)
620  return l1_id;
621 
622  /*
623  * Scan the map string to find how many bits are set in the string
624  * If more than one bit is set, then cache is shared.
625  */
626  is_shared = processor_is_cache_shared(buf);
627  if (is_shared) { /* L1 cache is shared */
628  physid = processor_physid_get(id);
629  coreid = processor_coreid_get(id);
630  l1_id = physid << 16 | coreid;
631  }
632 
633  return l1_id;
634 }
635 
645 {
646  uint32_t level;
647  uint32_t l2_id = id;
648  uint32_t coreid;
649  uint32_t physid;
650 
651  bool is_shared;
652  bool l3_cache_present = false;
653 
654  char filename[PATH_MAX];
655  char buf[MAX_LINE_LEN + 1];
656  char *str;
657 
658  FILE *fp;
659 
660  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
664  return l2_id;
665 
666  if (level != PROCESSORS_L2) {
667  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
671  return l2_id;
672 
674  l3_cache_present = true;
675  /*
676  * Set path to appropriate shared cpu file name
677  */
678  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
680  } else {
681  /*
682  * Set path to appropriate shared cpu file name
683  */
684  sprintf(filename, "%s%u/%s", PROCESSORS_CPU_DIR_PREFIX, id,
686  }
687 
688  /*
689  * Get the shared cpu map string.
690  */
691  fp = fopen(filename, "r");
692  if (fp == NULL)
693  return l2_id;
694 
695  str = fgets(buf, MAX_LINE_LEN, fp);
696  fclose(fp);
697  if (str == NULL)
698  return l2_id;
699 
700  /*
701  * Scan the map string to find how many bits are set in the string
702  */
703  is_shared = processor_is_cache_shared(buf);
704  if (is_shared) { /* L2 cache is shared */
705  physid = processor_physid_get(id);
706 
707  if (l3_cache_present) { /* L3 cache is present */
708  coreid = processor_coreid_get(id);
709  l2_id = physid << 16 | coreid;
710  } else
711  l2_id = physid;
712  }
713 
714  return l2_id;
715 }
716 
724 static inline uint32_t processor_pipelineid_get(m0_processor_nr_t id)
725 {
726  return id;
727 }
728 
745 {
746  M0_PRE(pn != NULL);
747 
750  return M0_ERR(-EINVAL);
751 
754  return M0_ERR(-EINVAL);
755 
758  return M0_ERR(-EINVAL);
759 
762  return M0_ERR(-EINVAL);
763 
766  return M0_ERR(-EINVAL);
767 
768  pn->pn_info.pd_id = id;
770 
771  return 0;
772 }
773 
780 static void processor_cache_destroy(void)
781 {
782  struct m0_list_link *node;
783  struct processor_node *pinfo;
784 
788  sys_cpus.pss_max = 0;
789 
790  /* Remove all the processor nodes. */
792  while((struct m0_list *)node != &sys_cpus.pss_head) {
794  m0_list_del(&pinfo->pn_link);
795  m0_free(pinfo);
797  }
799 }
800 
817 {
818  int rc;
819  uint32_t cpuid;
820  char *dirp = getenv(PROCESSORS_INFO_ENV);
821  char *str;
822  char cwd[PATH_MAX];
823  struct processor_node *pn;
824 
825  if (dirp == NULL)
826  dirp = PROCESSORS_SYSFS_DIR;
827 
828  /*
829  * Obtain current working directory.
830  */
831  str = getcwd(cwd, sizeof(cwd) - 1);
832  if (str == NULL)
833  return -errno;
834 
835  /*
836  * Change directory to desired "sysfs" directory.
837  * Subsequent functions will use file names "relative" to syfs dir.
838  * Subsequent function will work in the context of "sysfs" directory.
839  */
840  rc = chdir(dirp);
841  if (rc != 0)
842  return -errno;
843 
844  /*
845  * Now get the summary of max/possible/avail/online CPUs
846  * All these functions will collect summary in 'sys_cpus'.
847  */
848 
851  rc = chdir(cwd);
852  if (rc != 0)
853  M0_LOG(M0_ERROR, "failed to chdir to '%s'", (char*)cwd);
854  return M0_ERR(-EINVAL);
855  }
856 
858  if (rc != 0) {
859  int rc2 = chdir(cwd);
860  if (rc2 != 0)
861  M0_LOG(M0_ERROR, "failed to chdir to '%s'", (char*)cwd);
862  return M0_RC(rc);
863  }
864 
866  if (rc != 0) {
867  int rc2;
869  rc2 = chdir(cwd);
870  if (rc2 != 0)
871  M0_LOG(M0_ERROR, "failed to chdir to '%s'", (char*)cwd);
872  return M0_RC(rc);
873  }
874 
876  if (rc != 0) {
877  int rc2;
880  rc2 = chdir(cwd);
881  if (rc2 != 0)
882  M0_LOG(M0_ERROR, "failed to chdir to '%s'", (char*)cwd);
883  return M0_RC(rc);
884  }
885 
887 
888  /*
889  * Using present/available CPU mask get details of each processor.
890  */
891  for (cpuid = 0; cpuid < sys_cpus.pss_avail_map.b_nr; ++cpuid) {
892  if (m0_bitmap_get(&sys_cpus.pss_avail_map, cpuid)) {
893  M0_ALLOC_PTR(pn);
894  if (pn == NULL) {
896  return M0_ERR(-ENOMEM);
897  }
898  rc = processor_info_get(cpuid, pn);
899  if (rc != 0)
900  m0_free(pn);
901  else
903 
904  } /* if - processor is present on the system */
905 
906  }/* for - scan all the available processors */
907 
910  rc = chdir(cwd);
911  if (rc != 0)
912  M0_LOG(M0_ERROR, "failed to chdir to '%s'", (char*)cwd);
913  return M0_ERR(-ENODATA);
914  }
915 
916  /*
917  * Change back to previous working dir
918  */
919  rc = chdir(cwd);
920  if (rc != 0)
921  return -errno;
922  return 0;
923 }
924 
932  const struct m0_bitmap *src)
933 {
934  M0_PRE(dst->b_nr >= sys_cpus.pss_max);
936 }
937 
939 {
940  return m0_thread_confine(&data->ptd_thread, &data->ptd_cpu_map);
941 }
942 
944 {
946 
947  data->ptd_success = idx == data->ptd_idx;
948 }
949 
960 static int processor_getcpu_check(bool *success)
961 {
962  struct getcpu_thr_data *tdata;
963  struct m0_bitmap map_online = {};
964  size_t cpu_max;
965  size_t cpu_nr;
966  size_t i;
967  size_t j;
968  bool result = true;
969  int rc;
970  int rc2;
971 
972  cpu_max = m0_processor_nr_max();
973  rc = m0_bitmap_init(&map_online, cpu_max);
974  if (rc != 0)
975  return M0_RC(rc);
976  m0_processors_online(&map_online);
977  cpu_nr = m0_bitmap_set_nr(&map_online);
978 
979  M0_ALLOC_ARR(tdata, cpu_nr);
980  if (tdata == NULL) {
981  m0_bitmap_fini(&map_online);
982  return M0_ERR(-ENOMEM);
983  }
984 
985  for (i = 0, j = 0; i < map_online.b_nr; ++i) {
986  if (!m0_bitmap_get(&map_online, i))
987  continue;
988 
989  tdata[j].ptd_idx = (m0_processor_nr_t)i;
990  rc = m0_bitmap_init(&tdata[j].ptd_cpu_map, cpu_max);
991  if (rc != 0)
992  break;
993  m0_bitmap_set(&tdata[j].ptd_cpu_map, i, true);
994 
995  rc = M0_THREAD_INIT(&tdata[j].ptd_thread,
996  struct getcpu_thr_data *,
998  &tdata[j], "m0_getcpu_check");
999  if (rc != 0) {
1000  m0_bitmap_fini(&tdata[i].ptd_cpu_map);
1001  break;
1002  }
1003  ++j;
1004  }
1005  M0_ASSERT(ergo(rc == 0, j == cpu_nr));
1006 
1007  for (i = 0; i < j; ++i) {
1008  rc2 = m0_thread_join(&tdata[i].ptd_thread);
1009  rc = rc ?: rc2;
1010  result = rc2 == 0 && result && tdata[i].ptd_success;
1011  m0_thread_fini(&tdata[i].ptd_thread);
1012  m0_bitmap_fini(&tdata[i].ptd_cpu_map);
1013  }
1014 
1015  m0_free(tdata);
1016  m0_bitmap_fini(&map_online);
1017 
1018  if (rc == 0)
1019  *success = result;
1020  return M0_RC(rc);
1021 }
1022 
1023 static int processor_getcpu_init(void)
1024 {
1026  bool success;
1027  int rc;
1028 
1029  pg->pg_getcpu_inited = true;
1030  pg->pg_getcpu_workaround = false;
1031  rc = processor_getcpu_check(&success);
1032  if (rc == 0 && !success) {
1033  M0_LOG(M0_WARN, "sched_getcpu(3) doesn't return expected"
1034  "values, fall back to syscall getcpu(2).");
1035  pg->pg_getcpu_workaround = true;
1036  rc = processor_getcpu_check(&success);
1037  if (rc == 0 && !success)
1038  rc = M0_ERR(-ENODEV);
1039  }
1040  if (rc != 0)
1041  pg->pg_getcpu_inited = false;
1042 
1043  return M0_RC(rc);
1044 }
1045 
1046 static void processor_getcpu_fini(void)
1047 {
1048 }
1049 
1050 #ifdef CONFIG_X86_64
1051 static void processor_cpuid_reg_get(unsigned opc, unsigned *r)
1052 {
1053  __asm__ __volatile__ ("cpuid\n\t"
1054  : "=a" (r[0]), "=b" (r[1]),
1055  "=c" (r[2]), "=d" (r[3])
1056  : "0" (opc), "1" (0), "2" (0));
1057 }
1058 #endif
1059 
1060 /* ---- Processor Interface Implementation ---- */
1061 
1062 M0_INTERNAL int m0_processors_init()
1063 {
1064  struct processor_global *pg;
1065  int rc;
1066 
1068  M0_ALLOC_PTR(pg);
1070  rc = pg == NULL ? M0_ERR(-ENOMEM) : 0;
1071  rc = rc ?: processors_summary_get();
1072  /* Required by processor_getcpu_init(). */
1073  processor_init = (rc == 0);
1074  rc = rc ?: processor_getcpu_init();
1075 
1076  if (rc != 0) {
1077  m0_free(pg);
1079  processor_init = false;
1080  }
1081  return M0_RC(rc);
1082 }
1083 
1084 M0_INTERNAL void m0_processors_fini()
1085 {
1089  m0_free0(&m0_get()->i_moddata[M0_MODULE_PROCESSOR]);
1090  processor_init = false;
1091 }
1092 
1094 {
1096  return sys_cpus.pss_max;
1097 }
1098 
1099 M0_INTERNAL void m0_processors_possible(struct m0_bitmap *map)
1100 {
1102  M0_PRE(map != NULL);
1104 }
1105 
1106 M0_INTERNAL void m0_processors_available(struct m0_bitmap *map)
1107 {
1109  M0_PRE(map != NULL);
1111 }
1112 
1113 M0_INTERNAL void m0_processors_online(struct m0_bitmap *map)
1114 {
1116  M0_PRE(map != NULL);
1118 }
1119 
1121  struct m0_processor_descr *pd)
1122 {
1123  struct processor_node *pinfo;
1124 
1126  M0_PRE(pd != NULL);
1127 
1129  struct processor_node, pn_link) {
1130  if (pinfo->pn_info.pd_id == id) {
1131  *pd = pinfo->pn_info;
1132  return 0;
1133  }/* if - matching CPU id found */
1134  }/* for - iterate over all the processor nodes */
1135 
1136  return M0_ERR(-EINVAL);
1137 }
1138 
1140 {
1142  unsigned cpu;
1143  int rc;
1144 
1145  M0_PRE(pg->pg_getcpu_inited);
1146 
1147  if (pg->pg_getcpu_workaround) {
1148  rc = syscall(SYS_getcpu, &cpu, NULL, NULL);
1149  if (rc < 0)
1151  } else {
1152  rc = sched_getcpu();
1153  cpu = rc < 0 ? M0_PROCESSORS_INVALID_ID : (unsigned)rc;
1154  }
1155  if (rc < 0)
1156  M0_LOG(M0_ERROR, "%s(): rc=%d errno=%d",
1157  pg->pg_getcpu_workaround ? "syscall" : "sched_getcpu",
1158  rc, errno);
1159  return cpu;
1160 }
1161 
1162 #ifdef CONFIG_X86_64
1163 M0_INTERNAL bool m0_processor_is_vm(void)
1164 {
1165  unsigned reg[4] = {};
1166 
1167  processor_cpuid_reg_get(0x1, reg);
1168  return (reg[2] & (1U << 31)) != 0;
1169 }
1170 #else
1171 M0_INTERNAL bool m0_processor_is_vm(void)
1172 {
1173  return false;
1174 }
1175 #endif
1176 
1177 
1178 #undef M0_TRACE_SUBSYSTEM
1179 
1182 /*
1183  * Local variables:
1184  * c-indentation-style: "K&R"
1185  * c-basic-offset: 8
1186  * tab-width: 8
1187  * fill-column: 80
1188  * scroll-step: 1
1189  * End:
1190  */
struct m0_bitmap pss_poss_map
Definition: processor.c:134
uint64_t id
Definition: cob.h:2380
#define PROCESSORS_PRESENT_FILE
Definition: processor.c:79
static void ptr(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)
Definition: dump.c:440
static uint32_t number_read(const char *filename)
Definition: processor.c:289
#define PROCESSORS_NODE_DIR
Definition: processor.c:75
#define PROCESSORS_CACHE3_LEVEL_FILE
Definition: processor.c:84
#define M0_PROCESSORS_INVALID_ID
Definition: processor.h:59
struct m0_list pss_head
Definition: processor.c:127
#define M0_PRE(cond)
M0_INTERNAL void m0_list_add(struct m0_list *head, struct m0_list_link *new)
Definition: list.c:113
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
M0_INTERNAL int m0_bitmap_init(struct m0_bitmap *map, size_t nr)
Definition: bitmap.c:86
M0_INTERNAL int struct dentry struct kstat * stat
Definition: dir.c:1433
#define NULL
Definition: misc.h:38
M0_INTERNAL int m0_thread_confine(struct m0_thread *q, const struct m0_bitmap *processors)
Definition: kthread.c:197
#define PROCESSORS_CACHE2_LEVEL_FILE
Definition: processor.c:83
M0_INTERNAL void m0_bitmap_fini(struct m0_bitmap *map)
Definition: bitmap.c:97
static struct m0_bufvec dst
Definition: xform.c:61
map
Definition: processor.c:112
#define PROCESSORS_CACHE1_SIZE_FILE
Definition: processor.c:90
m0_processor_nr_t ptd_idx
Definition: processor.c:170
Definition: idx_mock.c:52
#define ergo(a, b)
Definition: misc.h:293
M0_INTERNAL void m0_processors_possible(struct m0_bitmap *map)
Definition: processor.c:1099
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
M0_INTERNAL void m0_list_init(struct m0_list *head)
Definition: list.c:29
#define PROCESSORS_CACHE2_SHCPUMAP_FILE
Definition: processor.c:87
Definition: xcode.c:172
#define M0_LOG(level,...)
Definition: trace.h:167
enum m0_trace_level level
Definition: trace.c:111
struct m0_thread ptd_thread
Definition: processor.c:171
M0_INTERNAL m0_processor_nr_t m0_processor_nr_max(void)
Definition: processor.c:1093
static struct net_test_cmd_node * node
Definition: commands.c:72
static void getcpu_thr_func(struct getcpu_thr_data *data)
Definition: processor.c:943
struct m0_bufvec data
Definition: di.c:40
#define PROCESSORS_POSS_FILE
Definition: processor.c:78
M0_INTERNAL void m0_list_fini(struct m0_list *head)
Definition: list.c:36
M0_INTERNAL void m0_list_del(struct m0_list_link *old)
Definition: list.c:147
M0_INTERNAL void m0_processors_fini(void)
Definition: processor.c:1084
struct m0_processor_descr pn_info
Definition: processor.c:153
struct m0_bitmap pss_onln_map
Definition: processor.c:140
uint32_t pd_pipeline
Definition: processor.h:186
M0_INTERNAL size_t m0_bitmap_set_nr(const struct m0_bitmap *map)
Definition: bitmap.c:172
#define M0_THREAD_INIT(thread, TYPE, init, func, arg, namefmt,...)
Definition: thread.h:139
M0_INTERNAL struct m0 * m0_get(void)
Definition: instance.c:41
struct m0_bitmap pss_avail_map
Definition: processor.c:137
M0_INTERNAL m0_processor_nr_t m0_processor_id_get(void)
Definition: processor.c:1139
bool pg_getcpu_workaround
Definition: processor.c:165
#define PROCESSORS_COREID_FILE
Definition: processor.c:94
#define PROCESSORS_CACHE3_SHCPUMAP_FILE
Definition: processor.c:88
Definition: sock.c:887
uint32_t pd_numa_node
Definition: processor.h:173
#define PROCESSORS_ONLINE_FILE
Definition: processor.c:80
return M0_RC(rc)
#define PROCESSORS_NODE_STR
Definition: processor.c:99
static void processor_getcpu_fini(void)
Definition: processor.c:1046
bool pg_getcpu_inited
Definition: processor.c:160
int i
Definition: dir.c:1033
#define PROCESSORS_INFO_ENV
Definition: processor.c:71
return M0_ERR(-EOPNOTSUPP)
struct m0_list_link pn_link
Definition: processor.c:150
uint32_t m0_processor_nr_t
Definition: processor.h:62
map_type
Definition: pool.h:63
static int processor_map_type_set(enum map map_type)
Definition: processor.c:235
#define PROCESSORS_CPU_STR
Definition: processor.c:100
m0_processor_nr_t pd_id
Definition: processor.h:171
m0_processor_nr_t pss_max
Definition: processor.c:131
static struct processor_sys_summary sys_cpus
Definition: processor.c:179
struct m0_list_link * l_head
Definition: list.h:76
static size_t processor_l2_size_get(m0_processor_nr_t id)
Definition: processor.c:522
#define m0_free0(pptr)
Definition: memory.h:77
#define m0_list_for_each_entry(head, pos, type, member)
Definition: list.h:235
#define M0_ASSERT(cond)
static void processors_m0bitmap_copy(struct m0_bitmap *dst, const struct m0_bitmap *src)
Definition: processor.c:931
static uint32_t processor_l2_cacheid_get(m0_processor_nr_t id)
Definition: processor.c:644
static void processor_maxsz_get()
Definition: processor.c:315
#define PROCESSORS_MAX_FILE
Definition: processor.c:77
M0_INTERNAL int m0_processors_init(void)
Definition: processor.c:1062
static int getcpu_thr_init(struct getcpu_thr_data *data)
Definition: processor.c:938
static uint32_t processor_pipelineid_get(m0_processor_nr_t id)
Definition: processor.c:724
void m0_thread_fini(struct m0_thread *q)
Definition: thread.c:92
#define PROCESSORS_CACHE1_LEVEL_FILE
Definition: processor.c:82
static uint32_t processor_numanodeid_get(m0_processor_nr_t id)
Definition: processor.c:332
static int processor_info_get(m0_processor_nr_t id, struct processor_node *pn)
Definition: processor.c:744
M0_INTERNAL void m0_processors_online(struct m0_bitmap *map)
Definition: processor.c:1113
static bool processor_init
Definition: processor.c:180
#define M0_POST(cond)
#define PROCESSORS_CACHE2_SIZE_FILE
Definition: processor.c:91
M0_INTERNAL void m0_bitmap_set(struct m0_bitmap *map, size_t idx, bool val)
Definition: bitmap.c:139
M0_INTERNAL bool m0_list_is_empty(const struct m0_list *head)
Definition: list.c:42
static int processor_getcpu_check(bool *success)
Definition: processor.c:960
static size_t processor_l1_size_get(m0_processor_nr_t id)
Definition: processor.c:475
static uint32_t processor_physid_get(m0_processor_nr_t id)
Definition: processor.c:421
M0_INTERNAL void m0_bitmap_copy(struct m0_bitmap *dst, const struct m0_bitmap *src)
Definition: bitmap.c:158
Definition: list.h:72
static void processor_cache_destroy(void)
Definition: processor.c:780
static uint32_t processor_coreid_get(m0_processor_nr_t id)
Definition: processor.c:403
#define PROCESSORS_CPU_DIR_PREFIX
Definition: processor.c:97
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
static int r[NR]
Definition: thread.c:46
void * i_moddata[M0_MODULE_NR]
Definition: instance.h:94
M0_INTERNAL int m0_processor_describe(m0_processor_nr_t id, struct m0_processor_descr *pd)
Definition: processor.c:1120
M0_INTERNAL bool m0_bitmap_get(const struct m0_bitmap *map, size_t idx)
Definition: bitmap.c:105
static void processor_map_set(struct m0_bitmap *map, const char *mapstr)
Definition: processor.c:193
m0_bcount_t size
Definition: di.c:39
#define PROCESSORS_CACHE3_SIZE_FILE
Definition: processor.c:92
static int processors_summary_get()
Definition: processor.c:816
struct m0_bitmap ptd_cpu_map
Definition: processor.c:173
Definition: rcv_session.c:58
size_t b_nr
Definition: bitmap.h:44
static int processor_getcpu_init(void)
Definition: processor.c:1023
int num
Definition: bulk_if.c:54
void m0_free(void *data)
Definition: memory.c:146
M0_INTERNAL bool m0_processor_is_vm(void)
Definition: processor.c:1171
static uint32_t processor_l1_cacheid_get(m0_processor_nr_t id)
Definition: processor.c:582
#define PROCESSORS_SYSFS_DIR
Definition: processor.c:73
struct m0_pdclust_src_addr src
Definition: fd.c:108
int32_t rc
Definition: trigger_fop.h:47
#define m0_list_entry(link, type, member)
Definition: list.h:217
static bool processor_is_cache_shared(const char *mapstr)
Definition: processor.c:437
Definition: trace.h:478
M0_INTERNAL void m0_processors_available(struct m0_bitmap *map)
Definition: processor.c:1106
#define PROCESSORS_CACHE1_SHCPUMAP_FILE
Definition: processor.c:86
#define PROCESSORS_PHYSID_FILE
Definition: processor.c:95
#define M0_IMPOSSIBLE(fmt,...)