Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

affinity.c 2.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * Copyright (c) 2002-2004 Roland McGrath <roland@redhat.com>
  3. * Copyright (c) 2009-2018 Dmitry V. Levin <ldv@altlinux.org>
  4. * All rights reserved.
  5. *
  6. * SPDX-License-Identifier: LGPL-2.1-or-later
  7. */
  8. #include "defs.h"
  9. #include <sched.h>
  10. static unsigned int
  11. get_cpuset_size(void)
  12. {
  13. static unsigned int cpuset_size;
  14. if (!cpuset_size) {
  15. /*
  16. * If the cpuset size passed to sched_getaffinity is less
  17. * than necessary to store the bitmask, the kernel does not
  18. * look at the mask pointer and fails with EINVAL.
  19. *
  20. * If the cpuset size is large enough, the kernel fails with
  21. * EFAULT on inaccessible mask pointers.
  22. *
  23. * This undocumented kernel feature can be used to probe
  24. * the kernel and find out the minimal valid cpuset size
  25. * without allocating any memory for the CPU affinity mask.
  26. */
  27. cpuset_size = 128;
  28. while (cpuset_size &&
  29. sched_getaffinity(0, cpuset_size, NULL) == -1 &&
  30. EINVAL == errno) {
  31. cpuset_size <<= 1;
  32. }
  33. if (!cpuset_size)
  34. cpuset_size = 128;
  35. }
  36. return cpuset_size;
  37. }
  38. static void
  39. print_affinitylist(struct tcb *const tcp, const kernel_ulong_t addr,
  40. const unsigned int len)
  41. {
  42. const unsigned int max_size = get_cpuset_size();
  43. const unsigned int umove_size = len < max_size ? len : max_size;
  44. const unsigned int size =
  45. (umove_size + current_wordsize - 1) & -current_wordsize;
  46. const unsigned int ncpu = size * 8;
  47. void *cpu;
  48. if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
  49. !addr || !len || !(cpu = calloc(size, 1))) {
  50. printaddr(addr);
  51. return;
  52. }
  53. if (!umoven_or_printaddr(tcp, addr, umove_size, cpu)) {
  54. int i = 0;
  55. const char *sep = "";
  56. tprints("[");
  57. for (;; i++) {
  58. i = next_set_bit(cpu, i, ncpu);
  59. if (i < 0)
  60. break;
  61. tprintf("%s%d", sep, i);
  62. sep = ", ";
  63. }
  64. if (size < len)
  65. tprintf("%s...", sep);
  66. tprints("]");
  67. }
  68. free(cpu);
  69. }
  70. SYS_FUNC(sched_setaffinity)
  71. {
  72. const int pid = tcp->u_arg[0];
  73. const unsigned int len = tcp->u_arg[1];
  74. tprintf("%d, %u, ", pid, len);
  75. print_affinitylist(tcp, tcp->u_arg[2], len);
  76. return RVAL_DECODED;
  77. }
  78. SYS_FUNC(sched_getaffinity)
  79. {
  80. const int pid = tcp->u_arg[0];
  81. const unsigned int len = tcp->u_arg[1];
  82. if (entering(tcp)) {
  83. tprintf("%d, %u, ", pid, len);
  84. } else {
  85. print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval);
  86. }
  87. return 0;
  88. }