* Bind an interrupt event to the specified CPU. Note that not all * platforms support binding an interrupt to a CPU. For those * platforms this request will fail. Using a cpu id of NOCPU unbinds * the interrupt event. */
| 296 | * the interrupt event. |
| 297 | */ |
| 298 | static int |
| 299 | _intr_event_bind(struct intr_event *ie, int cpu, bool bindirq, bool bindithread) |
| 300 | { |
| 301 | lwpid_t id; |
| 302 | int error; |
| 303 | |
| 304 | /* Need a CPU to bind to. */ |
| 305 | if (cpu != NOCPU && CPU_ABSENT(cpu)) |
| 306 | return (EINVAL); |
| 307 | |
| 308 | if (ie->ie_assign_cpu == NULL) |
| 309 | return (EOPNOTSUPP); |
| 310 | |
| 311 | error = priv_check(curthread, PRIV_SCHED_CPUSET_INTR); |
| 312 | if (error) |
| 313 | return (error); |
| 314 | |
| 315 | /* |
| 316 | * If we have any ithreads try to set their mask first to verify |
| 317 | * permissions, etc. |
| 318 | */ |
| 319 | if (bindithread) { |
| 320 | mtx_lock(&ie->ie_lock); |
| 321 | if (ie->ie_thread != NULL) { |
| 322 | id = ie->ie_thread->it_thread->td_tid; |
| 323 | mtx_unlock(&ie->ie_lock); |
| 324 | error = cpuset_setithread(id, cpu); |
| 325 | if (error) |
| 326 | return (error); |
| 327 | } else |
| 328 | mtx_unlock(&ie->ie_lock); |
| 329 | } |
| 330 | if (bindirq) |
| 331 | error = ie->ie_assign_cpu(ie->ie_source, cpu); |
| 332 | if (error) { |
| 333 | if (bindithread) { |
| 334 | mtx_lock(&ie->ie_lock); |
| 335 | if (ie->ie_thread != NULL) { |
| 336 | cpu = ie->ie_cpu; |
| 337 | id = ie->ie_thread->it_thread->td_tid; |
| 338 | mtx_unlock(&ie->ie_lock); |
| 339 | (void)cpuset_setithread(id, cpu); |
| 340 | } else |
| 341 | mtx_unlock(&ie->ie_lock); |
| 342 | } |
| 343 | return (error); |
| 344 | } |
| 345 | |
| 346 | if (bindirq) { |
| 347 | mtx_lock(&ie->ie_lock); |
| 348 | ie->ie_cpu = cpu; |
| 349 | mtx_unlock(&ie->ie_lock); |
| 350 | } |
| 351 | |
| 352 | return (error); |
| 353 | } |
| 354 | |
| 355 | /* |
no test coverage detected