(root)/
strace-6.5/
src/
sched.c
       1  /*
       2   * Copyright (c) 2004 Ulrich Drepper <drepper@redhat.com>
       3   * Copyright (c) 2005 Roland McGrath <roland@redhat.com>
       4   * Copyright (c) 2012-2015 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2014-2023 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: LGPL-2.1-or-later
       9   */
      10  
      11  #include "defs.h"
      12  
      13  #include <sched.h>
      14  #include "sched_attr.h"
      15  
      16  #include "xlat/schedulers.h"
      17  #include "xlat/sched_flags.h"
      18  
      19  SYS_FUNC(sched_getscheduler)
      20  {
      21  	if (entering(tcp)) {
      22  		/* pid */
      23  		printpid(tcp, tcp->u_arg[0], PT_TGID);
      24  	} else if (!syserror(tcp)) {
      25  		tcp->auxstr = xlookup(schedulers, (kernel_ulong_t) tcp->u_rval);
      26  		return RVAL_STR;
      27  	}
      28  	return 0;
      29  }
      30  
      31  SYS_FUNC(sched_setscheduler)
      32  {
      33  	/* pid */
      34  	printpid(tcp, tcp->u_arg[0], PT_TGID);
      35  	tprint_arg_next();
      36  
      37  	/* policy */
      38  	printxval(schedulers, tcp->u_arg[1], "SCHED_???");
      39  	tprint_arg_next();
      40  
      41  	/* param */
      42  	printnum_int(tcp, tcp->u_arg[2], "%d");
      43  
      44  	return RVAL_DECODED;
      45  }
      46  
      47  SYS_FUNC(sched_getparam)
      48  {
      49  	if (entering(tcp)) {
      50  		/* pid */
      51  		printpid(tcp, tcp->u_arg[0], PT_TGID);
      52  		tprint_arg_next();
      53  	} else {
      54  		/* param */
      55  		printnum_int(tcp, tcp->u_arg[1], "%d");
      56  	}
      57  	return 0;
      58  }
      59  
      60  SYS_FUNC(sched_setparam)
      61  {
      62  	/* pid */
      63  	printpid(tcp, tcp->u_arg[0], PT_TGID);
      64  	tprint_arg_next();
      65  
      66  	/* param */
      67  	printnum_int(tcp, tcp->u_arg[1], "%d");
      68  
      69  	return RVAL_DECODED;
      70  }
      71  
      72  SYS_FUNC(sched_get_priority_min)
      73  {
      74  	/* policy */
      75  	printxval(schedulers, tcp->u_arg[0], "SCHED_???");
      76  
      77  	return RVAL_DECODED;
      78  }
      79  
      80  static int
      81  do_sched_rr_get_interval(struct tcb *const tcp,
      82  			 const print_obj_by_addr_fn print_ts)
      83  {
      84  	if (entering(tcp)) {
      85  		/* pid */
      86  		printpid(tcp, tcp->u_arg[0], PT_TGID);
      87  		tprint_arg_next();
      88  	} else {
      89  		/* tp */
      90  		if (syserror(tcp))
      91  			printaddr(tcp->u_arg[1]);
      92  		else
      93  			print_ts(tcp, tcp->u_arg[1]);
      94  	}
      95  	return 0;
      96  }
      97  
      98  #if HAVE_ARCH_TIME32_SYSCALLS
      99  SYS_FUNC(sched_rr_get_interval_time32)
     100  {
     101  	return do_sched_rr_get_interval(tcp, print_timespec32);
     102  }
     103  #endif
     104  
     105  SYS_FUNC(sched_rr_get_interval_time64)
     106  {
     107  	return do_sched_rr_get_interval(tcp, print_timespec64);
     108  }
     109  
     110  static void
     111  print_sched_attr(struct tcb *const tcp, const kernel_ulong_t addr,
     112  		 unsigned int usize)
     113  {
     114  	struct sched_attr attr = {};
     115  	unsigned int size;
     116  	bool is_set = false;
     117  
     118  	if (usize) {
     119  		/* called from sched_getattr */
     120  		size = usize <= sizeof(attr) ? usize : (unsigned) sizeof(attr);
     121  		if (umoven_or_printaddr(tcp, addr, size, &attr))
     122  			return;
     123  		/* the number of bytes written by the kernel */
     124  		size = attr.size;
     125  	} else {
     126  		/* called from sched_setattr */
     127  		is_set = true;
     128  
     129  		if (umove_or_printaddr(tcp, addr, &attr.size))
     130  			return;
     131  		usize = attr.size;
     132  		if (!usize)
     133  			usize = SCHED_ATTR_MIN_SIZE;
     134  		size = usize <= sizeof(attr) ? usize : (unsigned) sizeof(attr);
     135  		if (size >= SCHED_ATTR_MIN_SIZE) {
     136  			if (umoven_or_printaddr(tcp, addr, size, &attr))
     137  				return;
     138  		}
     139  	}
     140  
     141  	tprint_struct_begin();
     142  	PRINT_FIELD_U(attr, size);
     143  
     144  	if (size < SCHED_ATTR_MIN_SIZE)
     145  		goto end;
     146  
     147  	if (!is_set || (int)attr.sched_policy < 0 || !(attr.sched_flags & (SCHED_FLAG_KEEP_POLICY | SCHED_FLAG_KEEP_PARAMS))) {
     148  		tprint_struct_next();
     149  		PRINT_FIELD_XVAL(attr, sched_policy, schedulers,
     150  				 "SCHED_???");
     151  	}
     152  	tprint_struct_next();
     153  	PRINT_FIELD_FLAGS(attr, sched_flags, sched_flags, "SCHED_FLAG_???");
     154  
     155  
     156  	if (!is_set || !(attr.sched_flags & SCHED_FLAG_KEEP_PARAMS)) {
     157  		tprint_struct_next();
     158  		PRINT_FIELD_D(attr, sched_nice);
     159  		tprint_struct_next();
     160  		PRINT_FIELD_U(attr, sched_priority);
     161  		tprint_struct_next();
     162  		PRINT_FIELD_U(attr, sched_runtime);
     163  		tprint_struct_next();
     164  		PRINT_FIELD_U(attr, sched_deadline);
     165  		tprint_struct_next();
     166  		PRINT_FIELD_U(attr, sched_period);
     167  	}
     168  
     169  	if (size < SCHED_ATTR_SIZE_VER1)
     170  		goto end;
     171  
     172  	tprint_struct_next();
     173  	PRINT_FIELD_U(attr, sched_util_min);
     174  	tprint_struct_next();
     175  	PRINT_FIELD_U(attr, sched_util_max);
     176  
     177  end:
     178  	if ((is_set ? usize : attr.size) > size) {
     179  		tprint_struct_next();
     180  		tprint_more_data_follows();
     181  	}
     182  
     183  	tprint_struct_end();
     184  }
     185  
     186  SYS_FUNC(sched_setattr)
     187  {
     188  	if (entering(tcp)) {
     189  		/* pid */
     190  		printpid(tcp, tcp->u_arg[0], PT_TGID);
     191  		tprint_arg_next();
     192  
     193  		/* attr */
     194  		print_sched_attr(tcp, tcp->u_arg[1], 0);
     195  	} else {
     196  		struct sched_attr attr;
     197  
     198  		if (verbose(tcp) && tcp->u_error == E2BIG
     199  		    && umove(tcp, tcp->u_arg[1], &attr.size) == 0) {
     200  			tprint_value_changed();
     201  			tprint_struct_begin();
     202  			PRINT_FIELD_U(attr, size);
     203  			tprint_struct_end();
     204  		}
     205  		tprint_arg_next();
     206  
     207  		/* flags */
     208  		PRINT_VAL_U((unsigned int) tcp->u_arg[2]);
     209  	}
     210  
     211  	return 0;
     212  }
     213  
     214  SYS_FUNC(sched_getattr)
     215  {
     216  	if (entering(tcp)) {
     217  		/* pid */
     218  		printpid(tcp, tcp->u_arg[0], PT_TGID);
     219  		tprint_arg_next();
     220  	} else {
     221  		const unsigned int size = tcp->u_arg[2];
     222  
     223  		/* attr */
     224  		if (size)
     225  			print_sched_attr(tcp, tcp->u_arg[1], size);
     226  		else
     227  			printaddr(tcp->u_arg[1]);
     228  		tprint_arg_next();
     229  
     230  		/* size */
     231  #ifdef AARCH64
     232  		/*
     233  		 * Due to a subtle gcc bug that leads to miscompiled aarch64
     234  		 * kernels, the 3rd argument of sched_getattr is not quite 32-bit
     235  		 * as on other architectures.  For more details see
     236  		 * https://lists.strace.io/pipermail/strace-devel/2017-March/006085.html
     237  		 */
     238  		if (syserror(tcp)) {
     239  			tprint_flags_begin();
     240  			print_abnormal_hi(tcp->u_arg[2]);
     241  			PRINT_VAL_U(size);
     242  			tprint_flags_end();
     243  		} else
     244  #endif
     245  		{
     246  			PRINT_VAL_U(size);
     247  		}
     248  		tprint_arg_next();
     249  
     250  		/* flags */
     251  		PRINT_VAL_U((unsigned int) tcp->u_arg[3]);
     252  	}
     253  
     254  	return 0;
     255  }