1  /* Copyright (C) 1994-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <hurd.h>
      19  #include <hurd/resource.h>
      20  
      21  /* Set the priority of all processes specified by WHICH and WHO
      22     to PRIO.  Returns 0 on success, -1 on errors.  */
      23  int
      24  __setpriority (enum __priority_which which, id_t who, int prio)
      25  {
      26    error_t err;
      27    error_t pidloser, priloser;
      28    unsigned int npids, ntasks, nwin, nperm, nacces;
      29  
      30    error_t setonepriority (pid_t pid, struct procinfo *pi)
      31      {
      32        task_t task;
      33        error_t piderr = __USEPORT (PROC, __proc_pid2task (port, pid, &task));
      34        if (piderr == EPERM)
      35  	++nperm;
      36        if (piderr != ESRCH)
      37  	{
      38  	  ++npids;
      39  	  if (piderr && piderr != EPERM)
      40  	    pidloser = piderr;
      41  	}
      42        if (! piderr)
      43  	{
      44  	  error_t prierr;
      45  	  ++ntasks;
      46  #ifdef POLICY_TIMESHARE_BASE_COUNT
      47  	  {
      48  	    /* XXX This assumes timeshare policy.  */
      49  	    struct policy_timeshare_base base
      50  	      = { NICE_TO_MACH_PRIORITY (prio) };
      51  	    prierr = __task_policy (task, POLICY_TIMESHARE,
      52  				    (policy_base_t) &base,
      53  				    POLICY_TIMESHARE_BASE_COUNT,
      54  				    0, 1);
      55  	  }
      56  #else
      57  	  prierr = __task_priority (task, NICE_TO_MACH_PRIORITY (prio), 1);
      58  #endif
      59  	  __mach_port_deallocate (__mach_task_self (), task);
      60  	  switch (prierr)
      61  	    {
      62  	    case KERN_FAILURE:
      63  	      ++nacces;
      64  	      break;
      65  	    case KERN_SUCCESS:
      66  	      ++nwin;
      67  	      break;
      68  	    case KERN_INVALID_ARGUMENT: /* Task died.  */
      69  	      --npids;
      70  	      --ntasks;
      71  	      break;
      72  	    default:
      73  	      priloser = prierr;
      74  	    }
      75  	}
      76        return 0;
      77      }
      78  
      79    npids = ntasks = nwin = nperm = nacces = 0;
      80    pidloser = priloser = 0;
      81    err = _hurd_priority_which_map (which, who, setonepriority, 0);
      82  
      83    if (!err && npids == 0)
      84      /* No error, but no pids found.  */
      85      err = ESRCH;
      86    else if (nperm == npids)
      87      /* Got EPERM from proc_task2pid for every process.  */
      88      err = EPERM;
      89    else if (nacces == ntasks)
      90      /* Got KERN_FAILURE from task_priority for every task.  */
      91      err = EACCES;
      92    else if (nwin == 0)
      93      err = pidloser ?: priloser;
      94  
      95    return err ? __hurd_fail (err) : 0;
      96  }
      97  libc_hidden_def (__setpriority)
      98  weak_alias (__setpriority, setpriority)