Skip to content

Commit

Permalink
powercap: idle_inject: Replace zero-length array with flexible-array …
Browse files Browse the repository at this point in the history
…member

The current codebase makes use of the zero-length array language
extension to the C90 standard, but the preferred mechanism to declare
variable-length types such as these ones is a flexible array member[1][2],
introduced in C99:

struct foo {
        int stuff;
        struct boo array[];
};

By making use of the mechanism above, we will get a compiler warning
in case the flexible array does not occur last in the structure, which
will help us prevent some kind of undefined behavior bugs from being
inadvertently introduced[3] to the codebase from now on.

Also, notice that, dynamic memory allocations won't be affected by
this change:

"Flexible array members have incomplete type, and so the sizeof operator
may not be applied. As a quirk of the original implementation of
zero-length arrays, sizeof evaluates to zero."[1]

Lastly, fix the following checkpatch warning:
WARNING: Prefer 'unsigned long' over 'unsigned long int' as the int is unnecessary
+	unsigned long int cpumask[];

This issue was found with the help of Coccinelle.

[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
[2] KSPP/linux#21
[3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour")

Signed-off-by: Gustavo A. R. Silva <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
Signed-off-by: Rsyd58 <[email protected]>
  • Loading branch information
GustavoARSilva authored and Rsyd58 committed Nov 25, 2024
1 parent 0d443a3 commit eff00b9
Show file tree
Hide file tree
Showing 5 changed files with 8 additions and 119 deletions.
1 change: 0 additions & 1 deletion drivers/powercap/Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
obj-$(CONFIG_POWERCAP) += powercap_sys.o
obj-$(CONFIG_INTEL_RAPL) += intel_rapl.o
obj-$(CONFIG_IDLE_INJECT) += idle_inject.o
4 changes: 2 additions & 2 deletions drivers/powercap/idle_inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
#include <linux/slab.h>
#include <linux/smpboot.h>

#include <uapi/linux/sched/types.h>
//#include <uapi/linux/sched/types.h>

/**
* struct idle_inject_thread - task on/off switch structure
Expand All @@ -67,7 +67,7 @@ struct idle_inject_device {
struct hrtimer timer;
unsigned int idle_duration_us;
unsigned int run_duration_us;
unsigned long int cpumask[0];
unsigned long cpumask[];
};

static DEFINE_PER_CPU(struct idle_inject_thread, idle_inject_thread);
Expand Down
3 changes: 2 additions & 1 deletion drivers/thermal/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ thermal_sys-$(CONFIG_THERMAL_GOV_LOW_LIMITS) += gov_low_limits.o
thermal_sys-$(CONFIG_THERMAL_GOV_POWER_ALLOCATOR) += power_allocator.o

# cpufreq cooling
thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
thermal_sys-$(CONFIG_CPU_THERMAL) += cpufreq_cooling.o
thermal_sys-$(CONFIG_CPU_IDLE_THERMAL) += cpuidle_cooling.o

# clock cooling
thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o
Expand Down
1 change: 1 addition & 0 deletions include/linux/cpuidle.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ extern void cpuidle_resume(void);
extern int cpuidle_enable_device(struct cpuidle_device *dev);
extern void cpuidle_disable_device(struct cpuidle_device *dev);
extern int cpuidle_play_dead(void);
extern void cpuidle_use_deepest_state(bool enable);

extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev);
static inline struct cpuidle_device *cpuidle_get_device(void)
Expand Down
118 changes: 3 additions & 115 deletions kernel/sched/idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ void play_idle(unsigned long duration_us)

rcu_sleep_check();
preempt_disable();
current->flags |= PF_IDLE;
current->flags |= PF_WAKE_UP_IDLE;
cpuidle_use_deepest_state(true);

it.done = 0;
Expand All @@ -325,10 +325,10 @@ void play_idle(unsigned long duration_us)
HRTIMER_MODE_REL_PINNED);

while (!READ_ONCE(it.done))
do_idle();
cpu_idle_loop();

cpuidle_use_deepest_state(false);
current->flags &= ~PF_IDLE;
current->flags &= ~PF_WAKE_UP_IDLE;

preempt_fold_need_resched();
preempt_enable();
Expand Down Expand Up @@ -357,115 +357,3 @@ void cpu_startup_entry(enum cpuhp_state state)
cpu_idle_loop();
}

/*
* idle-task scheduling class.
*/

#ifdef CONFIG_SMP
static int
select_task_rq_idle(struct task_struct *p, int cpu, int sd_flag, int flags)
{
return task_cpu(p); /* IDLE tasks as never migrated */
}
#endif

/*
* Idle tasks are unconditionally rescheduled:
*/
static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int flags)
{
resched_curr(rq);
}

static struct task_struct *
pick_next_task_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
{
put_prev_task(rq, prev);
update_idle_core(rq);
schedstat_inc(rq->sched_goidle);

return rq->idle;
}

/*
* It is not legal to sleep in the idle task - print a warning
* message if some code attempts to do it:
*/
static void
dequeue_task_idle(struct rq *rq, struct task_struct *p, int flags)
{
raw_spin_unlock_irq(&rq->lock);
printk(KERN_ERR "bad: scheduling from the idle thread!\n");
dump_stack();
raw_spin_lock_irq(&rq->lock);
}

static void put_prev_task_idle(struct rq *rq, struct task_struct *prev)
{
}

/*
* scheduler tick hitting a task of our scheduling class.
*
* NOTE: This function can be called remotely by the tick offload that
* goes along full dynticks. Therefore no local assumption can be made
* and everything must be accessed through the @rq and @curr passed in
* parameters.
*/
static void task_tick_idle(struct rq *rq, struct task_struct *curr, int queued)
{
}

static void set_curr_task_idle(struct rq *rq)
{
}

static void switched_to_idle(struct rq *rq, struct task_struct *p)
{
BUG();
}

static void
prio_changed_idle(struct rq *rq, struct task_struct *p, int oldprio)
{
BUG();
}

static unsigned int get_rr_interval_idle(struct rq *rq, struct task_struct *task)
{
return 0;
}

static void update_curr_idle(struct rq *rq)
{
}

/*
* Simple, special scheduling class for the per-CPU idle tasks:
*/
const struct sched_class idle_sched_class = {
/* .next is NULL */
/* no enqueue/yield_task for idle tasks */

/* dequeue is not valid, we print a debug message there: */
.dequeue_task = dequeue_task_idle,

.check_preempt_curr = check_preempt_curr_idle,

.pick_next_task = pick_next_task_idle,
.put_prev_task = put_prev_task_idle,

#ifdef CONFIG_SMP
.select_task_rq = select_task_rq_idle,
.set_cpus_allowed = set_cpus_allowed_common,
#endif

.set_curr_task = set_curr_task_idle,
.task_tick = task_tick_idle,

.get_rr_interval = get_rr_interval_idle,

.prio_changed = prio_changed_idle,
.switched_to = switched_to_idle,
.update_curr = update_curr_idle,
};

0 comments on commit eff00b9

Please sign in to comment.