1 /* Thread Priority Protect helpers.
2 Copyright (C) 2006-2014 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
28 int __sched_fifo_min_prio
= -1;
29 int __sched_fifo_max_prio
= -1;
32 __init_sched_fifo_prio (void)
34 __sched_fifo_max_prio
= sched_get_priority_max (SCHED_FIFO
);
35 atomic_write_barrier ();
36 __sched_fifo_min_prio
= sched_get_priority_min (SCHED_FIFO
);
40 __pthread_tpp_change_priority (int previous_prio
, int new_prio
)
42 struct pthread
*self
= THREAD_SELF
;
43 struct priority_protection_data
*tpp
= THREAD_GETMEM (self
, tpp
);
47 if (__sched_fifo_min_prio
== -1)
48 __init_sched_fifo_prio ();
50 size_t size
= sizeof *tpp
;
51 size
+= (__sched_fifo_max_prio
- __sched_fifo_min_prio
+ 1)
52 * sizeof (tpp
->priomap
[0]);
53 tpp
= calloc (size
, 1);
56 tpp
->priomax
= __sched_fifo_min_prio
- 1;
57 THREAD_SETMEM (self
, tpp
, tpp
);
60 assert (new_prio
== -1
61 || (new_prio
>= __sched_fifo_min_prio
62 && new_prio
<= __sched_fifo_max_prio
));
63 assert (previous_prio
== -1
64 || (previous_prio
>= __sched_fifo_min_prio
65 && previous_prio
<= __sched_fifo_max_prio
));
67 int priomax
= tpp
->priomax
;
68 int newpriomax
= priomax
;
71 if (tpp
->priomap
[new_prio
- __sched_fifo_min_prio
] + 1 == 0)
73 ++tpp
->priomap
[new_prio
- __sched_fifo_min_prio
];
74 if (new_prio
> priomax
)
75 newpriomax
= new_prio
;
78 if (previous_prio
!= -1)
80 if (--tpp
->priomap
[previous_prio
- __sched_fifo_min_prio
] == 0
81 && priomax
== previous_prio
82 && previous_prio
> new_prio
)
85 for (i
= previous_prio
- 1; i
>= __sched_fifo_min_prio
; --i
)
86 if (tpp
->priomap
[i
- __sched_fifo_min_prio
])
92 if (priomax
== newpriomax
)
95 lll_lock (self
->lock
, LLL_PRIVATE
);
97 tpp
->priomax
= newpriomax
;
101 if ((self
->flags
& ATTR_FLAG_SCHED_SET
) == 0)
103 if (__sched_getparam (self
->tid
, &self
->schedparam
) != 0)
106 self
->flags
|= ATTR_FLAG_SCHED_SET
;
109 if ((self
->flags
& ATTR_FLAG_POLICY_SET
) == 0)
111 self
->schedpolicy
= __sched_getscheduler (self
->tid
);
112 if (self
->schedpolicy
== -1)
115 self
->flags
|= ATTR_FLAG_POLICY_SET
;
120 struct sched_param sp
= self
->schedparam
;
121 if (sp
.sched_priority
< newpriomax
|| sp
.sched_priority
< priomax
)
123 if (sp
.sched_priority
< newpriomax
)
124 sp
.sched_priority
= newpriomax
;
126 if (__sched_setscheduler (self
->tid
, self
->schedpolicy
, &sp
) < 0)
131 lll_unlock (self
->lock
, LLL_PRIVATE
);
137 __pthread_current_priority (void)
139 struct pthread
*self
= THREAD_SELF
;
140 if ((self
->flags
& (ATTR_FLAG_POLICY_SET
| ATTR_FLAG_SCHED_SET
))
141 == (ATTR_FLAG_POLICY_SET
| ATTR_FLAG_SCHED_SET
))
142 return self
->schedparam
.sched_priority
;
146 lll_lock (self
->lock
, LLL_PRIVATE
);
148 if ((self
->flags
& ATTR_FLAG_SCHED_SET
) == 0)
150 if (__sched_getparam (self
->tid
, &self
->schedparam
) != 0)
153 self
->flags
|= ATTR_FLAG_SCHED_SET
;
156 if ((self
->flags
& ATTR_FLAG_POLICY_SET
) == 0)
158 self
->schedpolicy
= __sched_getscheduler (self
->tid
);
159 if (self
->schedpolicy
== -1)
162 self
->flags
|= ATTR_FLAG_POLICY_SET
;
166 result
= self
->schedparam
.sched_priority
;
168 lll_unlock (self
->lock
, LLL_PRIVATE
);