diff --git a/sched/sched/sched_foreach.c b/sched/sched/sched_foreach.c index e8c8a25482b..c5df9cd5f61 100644 --- a/sched/sched/sched_foreach.c +++ b/sched/sched/sched_foreach.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sched/sched_foreach.c * - * Copyright (C) 2007, 2009, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009, 2016, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -51,9 +51,15 @@ * Name: sched_foreach * * Description: - * Enumerate over each task and provide the TCB of each - * task to a user callback functions. Interrupts will be - * disabled throughout this enumeration! + * Enumerate over each task and provide the TCB of each task to a user + * callback functions. + * + * NOTE: This function examines the TCB and calls each handler within a + * critical section. However, that critical section is released and + * reacquired for each TCB. When it is released, there may be changes in + * tasking. If the caller requires absolute stability through the + * traversal, then the caller should establish the critical section BEFORE + * calling this function. * * Input Parameters: * handler - The function to be called with the TCB of @@ -62,26 +68,27 @@ * Returned Value: * None * - * Assumptions: - * ****************************************************************************/ void sched_foreach(sched_foreach_t handler, FAR void *arg) { - irqstate_t flags = enter_critical_section(); + irqstate_t flags; int ndx; - /* Vist each active task */ + /* Visit each active task */ for (ndx = 0; ndx < CONFIG_MAX_TASKS; ndx++) { + /* This test and the function call must be atomic */ + + flags = enter_critical_section(); if (g_pidhash[ndx].tcb) { handler(g_pidhash[ndx].tcb, arg); } - } - leave_critical_section(flags); + leave_critical_section(flags); + } } diff --git a/sched/sched/sched_gettcb.c b/sched/sched/sched_gettcb.c index a5fc20c2787..20554771208 100644 --- a/sched/sched/sched_gettcb.c +++ b/sched/sched/sched_gettcb.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sched/sched_gettcb.c * - * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009, 2011, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -41,6 +41,8 @@ #include +#include "nuttx/irq.h" + #include "sched/sched.h" /**************************************************************************** @@ -51,15 +53,22 @@ * Name: sched_gettcb * * Description: - * Given a task ID, this function will return - * the a pointer to the corresponding TCB (or NULL if there - * is no such task ID). + * Given a task ID, this function will return the a pointer to the + * corresponding TCB (or NULL if there is no such task ID). + * + * NOTE: This function holds a critical section while examining TCB data + * data structures but releases that critical section before returning. + * When it is released, the TCB may become unstable. If the caller + * requires absolute stability while using the TCB, then the caller + * should establish the critical section BEFORE calling this function and + * hold that critical section as long as necessary. * ****************************************************************************/ FAR struct tcb_s *sched_gettcb(pid_t pid) { FAR struct tcb_s *ret = NULL; + irqstate_t flags; int hash_ndx; /* Verify that the PID is within range */ @@ -70,6 +79,14 @@ FAR struct tcb_s *sched_gettcb(pid_t pid) hash_ndx = PIDHASH(pid); + /* The test and the return setup should be atomic. This still does + * not provide proper protection if the recipient of the TCB does not + * also protect against the task associated with the TCB from + * terminating asynchronously. + */ + + flags = spin_lock_irqsave(); + /* Verify that the correct TCB was found. */ if (pid == g_pidhash[hash_ndx].pid) @@ -78,6 +95,8 @@ FAR struct tcb_s *sched_gettcb(pid_t pid) ret = g_pidhash[hash_ndx].tcb; } + + spin_unlock_irqsave(); } /* Return the TCB. */