1 /* Thread Priority Protect helpers.
2 Copyright (C) 2006, 2007 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, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 int __sched_fifo_min_prio
= -1;
30 int __sched_fifo_max_prio
= -1;
33 __init_sched_fifo_prio (void)
35 __sched_fifo_max_prio
= sched_get_priority_max (SCHED_FIFO
);
36 atomic_write_barrier ();
37 __sched_fifo_min_prio
= sched_get_priority_min (SCHED_FIFO
);
41 __pthread_tpp_change_priority (int previous_prio
, int new_prio
)
43 struct pthread
*self
= THREAD_SELF
;
44 struct priority_protection_data
*tpp
= THREAD_GETMEM (self
, tpp
);
48 if (__sched_fifo_min_prio
== -1)
49 __init_sched_fifo_prio ();
51 size_t size
= sizeof *tpp
;
52 size
+= (__sched_fifo_max_prio
- __sched_fifo_min_prio
+ 1)
53 * sizeof (tpp
->priomap
[0]);
54 tpp
= calloc (size
, 1);
57 tpp
->priomax
= __sched_fifo_min_prio
- 1;
58 THREAD_SETMEM (self
, tpp
, tpp
);
61 assert (new_prio
== -1
62 || (new_prio
>= __sched_fifo_min_prio
63 && new_prio
<= __sched_fifo_max_prio
));
64 assert (previous_prio
== -1
65 || (previous_prio
>= __sched_fifo_min_prio
66 && previous_prio
<= __sched_fifo_max_prio
));
68 int priomax
= tpp
->priomax
;
69 int newpriomax
= priomax
;
72 if (tpp
->priomap
[new_prio
- __sched_fifo_min_prio
] + 1 == 0)
74 ++tpp
->priomap
[new_prio
- __sched_fifo_min_prio
];
75 if (new_prio
> priomax
)
76 newpriomax
= new_prio
;
79 if (previous_prio
!= -1)
81 if (--tpp
->priomap
[previous_prio
- __sched_fifo_min_prio
] == 0
82 && priomax
== previous_prio
83 && previous_prio
> new_prio
)
86 for (i
= previous_prio
- 1; i
>= __sched_fifo_min_prio
; --i
)
87 if (tpp
->priomap
[i
- __sched_fifo_min_prio
])
93 if (priomax
== newpriomax
)
96 lll_lock (self
->lock
, LLL_PRIVATE
);
98 tpp
->priomax
= newpriomax
;
102 if ((self
->flags
& ATTR_FLAG_SCHED_SET
) == 0)
104 if (__sched_getparam (self
->tid
, &self
->schedparam
) != 0)
107 self
->flags
|= ATTR_FLAG_SCHED_SET
;
110 if ((self
->flags
& ATTR_FLAG_POLICY_SET
) == 0)
112 self
->schedpolicy
= __sched_getscheduler (self
->tid
);
113 if (self
->schedpolicy
== -1)
116 self
->flags
|= ATTR_FLAG_POLICY_SET
;
121 struct sched_param sp
= self
->schedparam
;
122 if (sp
.sched_priority
< newpriomax
|| sp
.sched_priority
< priomax
)
124 if (sp
.sched_priority
< newpriomax
)
125 sp
.sched_priority
= newpriomax
;
127 if (__sched_setscheduler (self
->tid
, self
->schedpolicy
, &sp
) < 0)
132 lll_unlock (self
->lock
, LLL_PRIVATE
);
138 __pthread_current_priority (void)
140 struct pthread
*self
= THREAD_SELF
;
141 if ((self
->flags
& (ATTR_FLAG_POLICY_SET
| ATTR_FLAG_SCHED_SET
))
142 == (ATTR_FLAG_POLICY_SET
| ATTR_FLAG_SCHED_SET
))
143 return self
->schedparam
.sched_priority
;
147 lll_lock (self
->lock
, LLL_PRIVATE
);
149 if ((self
->flags
& ATTR_FLAG_SCHED_SET
) == 0)
151 if (__sched_getparam (self
->tid
, &self
->schedparam
) != 0)
154 self
->flags
|= ATTR_FLAG_SCHED_SET
;
157 if ((self
->flags
& ATTR_FLAG_POLICY_SET
) == 0)
159 self
->schedpolicy
= __sched_getscheduler (self
->tid
);
160 if (self
->schedpolicy
== -1)
163 self
->flags
|= ATTR_FLAG_POLICY_SET
;
167 result
= self
->schedparam
.sched_priority
;
169 lll_unlock (self
->lock
, LLL_PRIVATE
);