File: kvu_rtcaps.cpp

package info (click to toggle)
ecasound 2.9.3-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 6,292 kB
  • sloc: cpp: 39,475; sh: 4,335; lisp: 1,918; ansic: 1,883; makefile: 888; python: 617; ruby: 202
file content (152 lines) | stat: -rw-r--r-- 4,575 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// ------------------------------------------------------------------------
// kvu_rtcaps.h: Routines for utilizing POSIX RT extensions.
// Copyright (C) 2001-2003,2009 Kai Vehmanen
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
// ------------------------------------------------------------------------

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <iostream>
#include <unistd.h> /* getpid(), _POSIX_MEMLOCK */

#ifdef HAVE_SCHED_H
#include <sched.h>
#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h> /* mlockall(), munlockall() */
#endif
#include <pthread.h>

#include "kvu_rtcaps.h"

static bool kvu_check_for_sched_sub(int policy);

bool kvu_check_for_sched_sub(int policy)
{
  bool result = false;
#ifdef HAVE_SCHED_GETPARAM
  int curpid = getpid();

  /* store old scheduling params */
  struct sched_param prev_sparam;
  int ret = sched_getparam(curpid, &prev_sparam);
  if (ret == 0) {
    int prev_prio = prev_sparam.sched_priority;
    int prev_policy = sched_getscheduler(0);
    if (prev_policy >= 0) {
      /* get maximum priority for the tested policy */
      int min_prio = sched_get_priority_min(policy);
      if (min_prio >= 0) {
	struct sched_param sparam;
	sparam.sched_priority = min_prio;
	/* try to change scheduling according the new params */
        int ret = sched_setscheduler(curpid, policy, &sparam);
	if (ret == 0) {
	  /* test succeeded, restore old settings */
	  result = true;
	  sparam.sched_priority = prev_prio;
	  sched_setscheduler(curpid, prev_policy, &sparam);
	}
      }
    }
  } 
#else /* HAVE_SCHED_GETPARAM */
  std::cerr << "(libkvutils) kvu_rtcaps: warning! sched_getparam() not supported" << std::endl;
#endif
  return(result);
}

/**
 * Checks whether current process has privileges
 * to set scheduler to SCHED_FIFO.
 */
bool kvu_check_for_sched_fifo(void)
{
#ifdef HAVE_SCHED_H
  return(kvu_check_for_sched_sub(SCHED_FIFO));
#else
  std::cerr << "(libkvutils) kvu_rtcaps: warning! sched.h not available" << std::endl;
#endif
}

/**
 * Checks whether current process has privileges
 * to set scheduler to SCHED_RR.
 */
bool kvu_check_for_sched_rr(void)
{
#ifdef HAVE_SCHED_H
  return(kvu_check_for_sched_sub(SCHED_RR));
#else
  std::cerr << "(libkvutils) kvu_rtcaps: warning! sched.h not available" << std::endl;
#endif
}

/**
 * Checks whether mlockall() call is available 
 * and whether current process has privileges
 * to execute it.
 *
 * Note! Function issues an munlockall() call,
 *       which will free all previously locked
 *       memory areas for this process.
 */
bool kvu_check_for_mlockall(void)
{
  bool result = false;
#if defined(_POSIX_MEMLOCK) && defined(HAVE_MLOCKALL) && defined(HAVE_MUNLOCKALL) /* unistd.h */
  int ret = mlockall(MCL_CURRENT);
  if (ret == 0) {
    result = true;
    munlockall();
  }
#else
  std::cerr << "(libkvutils) kvu_rtcaps: warning! POSIX_MEMLOCK not supported" << std::endl;
#endif
  return(result);
}

/**
 * Sets the scheduler settings for calling thread.
 * If thread specific scheduler API (pthread_setscheduler, etc) 
 * is not available, function will fall back to process level
 * functions (sched_setscheduler).
 *
 * @param policy SCHED_OTHER, SCHED_FIFO, SCHED_RR (see sched_setscheduler(2))
 * @param priority value between 0 and 99 (see sched_setscheduler(2))
 *
 * @return Zero on success, non-zero on error.
 */
int kvu_set_thread_scheduling(int policy, int priority)
{
  int ret = 0;

#if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_PTHREAD_SELF)
  struct sched_param sparam;
  sparam.sched_priority = priority;
  ret = pthread_setschedparam(pthread_self(), policy, &sparam);
#elif defined(HAVE_SCHED_SETSCHEDULER)
  struct sched_param sparam;
  sparam.sched_priority = priority;
  ret = sched_setscheduler(0, policy, &sparam);
#else
  std::cerr << "(libkvutils) kvu_rtcaps: warning! unable to set scheduler settings" << std::endl;
#endif
  
  return ret;
}