diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 3ee50dc852..6458afa7ff 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -679,6 +679,12 @@ struct tcb_s FAR struct pthread_mutex_s *mhead; /* List of mutexes held by thread */ #endif + /* CPU load monitoring support ********************************************/ + +#ifdef CONFIG_SCHED_CPULOAD + uint32_t ticks; /* Number of ticks on this thread */ +#endif + /* Pre-emption monitor support ********************************************/ #ifdef CONFIG_SCHED_CRITMONITOR diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c index f54095f3dc..0f034aeb22 100644 --- a/sched/init/nx_start.c +++ b/sched/init/nx_start.c @@ -197,8 +197,7 @@ volatile pid_t g_lastpid; * 2. Is used to quickly map a process ID into a TCB. */ -FAR struct pidhash_s *g_pidhash; - +FAR struct tcb_s **g_pidhash; volatile int g_npidhash; /* This is a table of task lists. This table is indexed by the task stat @@ -547,15 +546,9 @@ void nx_start(void) g_npidhash <<= 1; } - g_pidhash = kmm_malloc(sizeof(struct pidhash_s) * g_npidhash); + g_pidhash = kmm_zalloc(sizeof(*g_pidhash) * g_npidhash); DEBUGASSERT(g_pidhash); - for (i = 0; i < g_npidhash; i++) - { - g_pidhash[i].tcb = NULL; - g_pidhash[i].pid = INVALID_PROCESS_ID; - } - /* IDLE Group Initialization **********************************************/ for (i = 0; i < CONFIG_SMP_NCPUS; i++) @@ -565,9 +558,8 @@ void nx_start(void) /* Assign the process ID(s) of ZERO to the idle task(s) */ - hashndx = PIDHASH(i); - g_pidhash[hashndx].tcb = &g_idletcb[i].cmn; - g_pidhash[hashndx].pid = i; + hashndx = PIDHASH(i); + g_pidhash[hashndx] = &g_idletcb[i].cmn; /* Allocate the IDLE group */ @@ -815,7 +807,7 @@ void nx_start(void) flags = enter_critical_section(); - tcb = g_pidhash[i].tcb; + tcb = g_pidhash[i]; if (tcb && (up_check_tcbstack(tcb) * 100 / tcb->adj_stack_size > CONFIG_STACK_USAGE_SAFE_PERCENT)) { diff --git a/sched/sched/sched.h b/sched/sched/sched.h index b87c0107db..4543a2a1ae 100644 --- a/sched/sched/sched.h +++ b/sched/sched/sched.h @@ -90,26 +90,6 @@ * Public Type Definitions ****************************************************************************/ -/* This structure defines the format of the hash table that is used to (1) - * determine if a task ID is unique, and (2) to map a process ID to its - * corresponding TCB. - * - * NOTE also that CPU load measurement data is retained in his table vs. in - * the TCB which would seem to be the more logic place. It is place in the - * hash table, instead, to facilitate CPU load adjustments on all threads - * during timer interrupt handling. nxsched_foreach() could do this too, but - * this would require a little more overhead. - */ - -struct pidhash_s -{ - FAR struct tcb_s *tcb; /* TCB assigned to this PID */ - pid_t pid; /* The full PID value */ -#ifdef CONFIG_SCHED_CPULOAD - uint32_t ticks; /* Number of ticks on this thread */ -#endif -}; - /* This structure defines an element of the g_tasklisttable[]. This table * is used to map a task_state enumeration to the corresponding task list. */ @@ -243,8 +223,7 @@ extern volatile pid_t g_lastpid; * 2. Is used to quickly map a process ID into a TCB. */ -extern FAR struct pidhash_s *g_pidhash; - +extern FAR struct tcb_s **g_pidhash; extern volatile int g_npidhash; /* This is a table of task lists. This table is indexed by the task stat diff --git a/sched/sched/sched_cpuload.c b/sched/sched/sched_cpuload.c index 5a16b70860..1f3fac3165 100644 --- a/sched/sched/sched_cpuload.c +++ b/sched/sched/sched_cpuload.c @@ -110,20 +110,11 @@ volatile uint32_t g_cpuload_total; static inline void nxsched_cpu_process_cpuload(int cpu) { - FAR struct tcb_s *rtcb = current_task(cpu); - int hash_index; + FAR struct tcb_s *rtcb = current_task(cpu); - /* Increment the count on the currently executing thread - * - * NOTE also that CPU load measurement data is retained in the g_pidhash - * table vs. in the TCB which would seem to be the more logic place. It - * is place in the hash table, instead, to facilitate CPU load adjustments - * on all threads during timer interrupt handling. nxsched_foreach() could - * do this too, but this would require a little more overhead. - */ + /* Increment the count on the currently executing thread */ - hash_index = PIDHASH(rtcb->pid); - g_pidhash[hash_index].ticks++; + rtcb->ticks++; /* Increment tick count. NOTE that the count is increment once for each * CPU on each sample interval. @@ -193,8 +184,8 @@ void weak_function nxsched_process_cpuload(void) for (i = 0; i < g_npidhash; i++) { - g_pidhash[i].ticks >>= 1; - total += g_pidhash[i].ticks; + g_pidhash[i]->ticks >>= 1; + total += g_pidhash[i]->ticks; } /* Save the new total. */ @@ -254,10 +245,10 @@ int clock_cpuload(int pid, FAR struct cpuload_s *cpuload) * do this too, but this would require a little more overhead. */ - if (g_pidhash[hash_index].tcb && g_pidhash[hash_index].pid == pid) + if (g_pidhash[hash_index] && g_pidhash[hash_index]->pid == pid) { cpuload->total = g_cpuload_total; - cpuload->active = g_pidhash[hash_index].ticks; + cpuload->active = g_pidhash[hash_index]->ticks; ret = OK; } diff --git a/sched/sched/sched_foreach.c b/sched/sched/sched_foreach.c index 0a074cb42b..fca65730ce 100644 --- a/sched/sched/sched_foreach.c +++ b/sched/sched/sched_foreach.c @@ -67,9 +67,9 @@ void nxsched_foreach(nxsched_foreach_t handler, FAR void *arg) { /* This test and the function call must be atomic */ - if (g_pidhash[ndx].tcb) + if (g_pidhash[ndx]) { - handler(g_pidhash[ndx].tcb, arg); + handler(g_pidhash[ndx], arg); } } diff --git a/sched/sched/sched_gettcb.c b/sched/sched/sched_gettcb.c index 373e21828f..9ee502cce3 100644 --- a/sched/sched/sched_gettcb.c +++ b/sched/sched/sched_gettcb.c @@ -76,11 +76,11 @@ FAR struct tcb_s *nxsched_get_tcb(pid_t pid) /* Verify that the correct TCB was found. */ - if (g_pidhash && pid == g_pidhash[hash_ndx].pid) + if (g_pidhash && pid == g_pidhash[hash_ndx]->pid) { /* Return the TCB associated with this pid (if any) */ - ret = g_pidhash[hash_ndx].tcb; + ret = g_pidhash[hash_ndx]; } leave_critical_section(flags); diff --git a/sched/sched/sched_releasetcb.c b/sched/sched/sched_releasetcb.c index 1f95c4e1ba..12fdde5fba 100644 --- a/sched/sched/sched_releasetcb.c +++ b/sched/sched/sched_releasetcb.c @@ -51,23 +51,20 @@ static void nxsched_releasepid(pid_t pid) irqstate_t flags = enter_critical_section(); int hash_ndx = PIDHASH(pid); +#ifdef CONFIG_SCHED_CPULOAD + /* Decrement the total CPU load count held by this thread from the + * total for all threads. + */ + + g_cpuload_total -= g_pidhash[hash_ndx]->ticks; +#endif + /* Make any pid associated with this hash available. Note: * no special precautions need be taken here because the * following action is atomic */ - g_pidhash[hash_ndx].tcb = NULL; - g_pidhash[hash_ndx].pid = INVALID_PROCESS_ID; - -#ifdef CONFIG_SCHED_CPULOAD - /* Decrement the total CPU load count held by this thread from the - * total for all threads. Then we can reset the count on this - * defunct thread to zero. - */ - - g_cpuload_total -= g_pidhash[hash_ndx].ticks; - g_pidhash[hash_ndx].ticks = 0; -#endif + g_pidhash[hash_ndx] = NULL; leave_critical_section(flags); } diff --git a/sched/sched/sched_verifytcb.c b/sched/sched/sched_verifytcb.c index 82db055e31..8703fd8c85 100644 --- a/sched/sched/sched_verifytcb.c +++ b/sched/sched/sched_verifytcb.c @@ -72,7 +72,7 @@ bool nxsched_verify_tcb(FAR struct tcb_s *tcb) bool vaild; flags = enter_critical_section(); - vaild = tcb == g_pidhash[PIDHASH(tcb->pid)].tcb; + vaild = tcb == g_pidhash[PIDHASH(tcb->pid)]; leave_critical_section(flags); return vaild; diff --git a/sched/task/task_setup.c b/sched/task/task_setup.c index c9e9eb73d7..7185d045dd 100644 --- a/sched/task/task_setup.c +++ b/sched/task/task_setup.c @@ -79,7 +79,7 @@ static const char g_noname[] = ""; static int nxtask_assign_pid(FAR struct tcb_s *tcb) { - FAR struct pidhash_s *pidhash; + FAR struct tcb_s **pidhash; pid_t next_pid; int hash_ndx; int i; @@ -117,15 +117,11 @@ retry: /* Check if there is a (potential) duplicate of this pid */ - if (!g_pidhash[hash_ndx].tcb) + if (!g_pidhash[hash_ndx]) { /* Assign this PID to the task */ - g_pidhash[hash_ndx].tcb = tcb; - g_pidhash[hash_ndx].pid = next_pid; -#ifdef CONFIG_SCHED_CPULOAD - g_pidhash[hash_ndx].ticks = 0; -#endif + g_pidhash[hash_ndx] = tcb; tcb->pid = next_pid; g_lastpid = next_pid; @@ -141,7 +137,7 @@ retry: * expand space. */ - pidhash = kmm_malloc(g_npidhash * 2 * sizeof(struct pidhash_s)); + pidhash = kmm_zalloc(g_npidhash * 2 * sizeof(*pidhash)); if (pidhash == NULL) { leave_critical_section(flags); @@ -150,24 +146,15 @@ retry: g_npidhash *= 2; - /* Reset the new hash table to the initial state */ - - for (i = 0; i < g_npidhash; i++) - { - pidhash[i].tcb = NULL; - pidhash[i].pid = INVALID_PROCESS_ID; - } - /* All original pid and hash_ndx are mismatch, * so we need to rebuild their relationship */ for (i = 0; i < g_npidhash / 2; i++) { - hash_ndx = PIDHASH(g_pidhash[i].pid); - DEBUGASSERT(pidhash[hash_ndx].tcb == NULL); - pidhash[hash_ndx].tcb = g_pidhash[i].tcb; - pidhash[hash_ndx].pid = g_pidhash[i].pid; + hash_ndx = PIDHASH(g_pidhash[i]->pid); + DEBUGASSERT(pidhash[hash_ndx] == NULL); + pidhash[hash_ndx] = g_pidhash[i]; } /* Release resource for original g_pidhash, using new g_pidhash */ diff --git a/tools/esp32/backtrace.gdbscript b/tools/esp32/backtrace.gdbscript index 79993ce492..41ae45011d 100644 --- a/tools/esp32/backtrace.gdbscript +++ b/tools/esp32/backtrace.gdbscript @@ -110,7 +110,7 @@ end define esp32_bt_pid set $_pid = $arg0 - set $_tcb = g_pidhash[$_pid].tcb + set $_tcb = g_pidhash[$_pid] if ($_tcb->pid == $_pid) set $_regs = $_tcb->xcp.regs printf "PID %d NAME %s\n", $_pid, $_tcb.name diff --git a/tools/nuttx-gdbinit b/tools/nuttx-gdbinit index 2875fa05db..89bb04ed46 100644 --- a/tools/nuttx-gdbinit +++ b/tools/nuttx-gdbinit @@ -54,7 +54,7 @@ define _examine_target if ($_target_examined == 0x0) _examine_arch - set $_tcb0 = g_pidhash[0].tcb + set $_tcb0 = g_pidhash[0] set $_xcp_nregs = sizeof($_tcb0->xcp.regs) / sizeof($_tcb0->xcp.regs[0]) set $_target_has_fpu = 0 @@ -385,7 +385,7 @@ define nxthread _examine_target _save_current_tcb set $hash = ($arg0 & ($_target_max_tasks - 1)) - set $tcb = g_pidhash[$hash].tcb + set $tcb = g_pidhash[$hash] if ($tcb != 0x0) _print_thread $tcb if ($argc == 1)