2021-03-26 20:55:06 +03:00
// SPDX-License-Identifier: GPL-2.0-only
# include "sched.h"
/*
* A simple wrapper around refcount . An allocated sched_core_cookie ' s
* address is used to compute the cookie of the task .
*/
struct sched_core_cookie {
refcount_t refcnt ;
} ;
unsigned long sched_core_alloc_cookie ( void )
{
struct sched_core_cookie * ck = kmalloc ( sizeof ( * ck ) , GFP_KERNEL ) ;
if ( ! ck )
return 0 ;
refcount_set ( & ck - > refcnt , 1 ) ;
sched_core_get ( ) ;
return ( unsigned long ) ck ;
}
void sched_core_put_cookie ( unsigned long cookie )
{
struct sched_core_cookie * ptr = ( void * ) cookie ;
if ( ptr & & refcount_dec_and_test ( & ptr - > refcnt ) ) {
kfree ( ptr ) ;
sched_core_put ( ) ;
}
}
unsigned long sched_core_get_cookie ( unsigned long cookie )
{
struct sched_core_cookie * ptr = ( void * ) cookie ;
if ( ptr )
refcount_inc ( & ptr - > refcnt ) ;
return cookie ;
}
/*
* sched_core_update_cookie - replace the cookie on a task
* @ p : the task to update
* @ cookie : the new cookie
*
* Effectively exchange the task cookie ; caller is responsible for lifetimes on
* both ends .
*
* Returns : the old cookie
*/
unsigned long sched_core_update_cookie ( struct task_struct * p , unsigned long cookie )
{
unsigned long old_cookie ;
struct rq_flags rf ;
struct rq * rq ;
bool enqueued ;
rq = task_rq_lock ( p , & rf ) ;
/*
* Since creating a cookie implies sched_core_get ( ) , and we cannot set
* a cookie until after we ' ve created it , similarly , we cannot destroy
* a cookie until after we ' ve removed it , we must have core scheduling
* enabled here .
*/
SCHED_WARN_ON ( ( p - > core_cookie | | cookie ) & & ! sched_core_enabled ( rq ) ) ;
enqueued = sched_core_enqueued ( p ) ;
if ( enqueued )
sched_core_dequeue ( rq , p ) ;
old_cookie = p - > core_cookie ;
p - > core_cookie = cookie ;
if ( enqueued )
sched_core_enqueue ( rq , p ) ;
/*
* If task is currently running , it may not be compatible anymore after
* the cookie change , so enter the scheduler on its CPU to schedule it
* away .
*/
if ( task_running ( rq , p ) )
resched_curr ( rq ) ;
task_rq_unlock ( rq , p , & rf ) ;
return old_cookie ;
}
static unsigned long sched_core_clone_cookie ( struct task_struct * p )
{
unsigned long cookie , flags ;
raw_spin_lock_irqsave ( & p - > pi_lock , flags ) ;
cookie = sched_core_get_cookie ( p - > core_cookie ) ;
raw_spin_unlock_irqrestore ( & p - > pi_lock , flags ) ;
return cookie ;
}
2021-03-29 16:18:35 +03:00
void sched_core_fork ( struct task_struct * p )
{
RB_CLEAR_NODE ( & p - > core_node ) ;
p - > core_cookie = sched_core_clone_cookie ( current ) ;
}
2021-03-26 20:55:06 +03:00
void sched_core_free ( struct task_struct * p )
{
sched_core_put_cookie ( p - > core_cookie ) ;
}