9
0
Fork 0

Divide struct tcb_s into structs task_tcb_s and pthread_tcb_s

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5611 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2013-02-04 21:24:00 +00:00
parent 7071ca9d21
commit f34406ac48
22 changed files with 332 additions and 176 deletions

View File

@ -4124,4 +4124,10 @@
* includes/nuttx/sched.h and Lots of files: Change name of _TCB to
struct tcb_s so that (1) it is consitent with other NuttX naming and
so that (2) the naming can handle some upcoming changes.
* includes/nuttx/sched.h and sched/: There are three TCB structures:
struct tcb_s is a generic common version, struct task_tcb_s is a
version for tasks and kernel threads and pthread_tcb_s is a version
for pthreads. By dividing the TCB structure into these variants,
pthreads do not have to be burdened by task-specific data structures
(and vice versa).

View File

@ -134,7 +134,7 @@ static void exec_ctors(FAR void *arg)
int exec_module(FAR const struct binary_s *binp)
{
FAR struct tcb_s *tcb;
FAR struct task_tcb_s *tcb;
#ifndef CONFIG_CUSTOM_STACK
FAR uint32_t *stack;
#endif
@ -156,7 +156,7 @@ int exec_module(FAR const struct binary_s *binp)
/* Allocate a TCB for the new task. */
tcb = (FAR struct tcb_s*)kzalloc(sizeof(struct tcb_s));
tcb = (FAR struct task_tcb_s*)kzalloc(sizeof(struct task_tcb_s));
if (!tcb)
{
err = ENOMEM;
@ -198,17 +198,17 @@ int exec_module(FAR const struct binary_s *binp)
*/
#ifdef CONFIG_PIC
tcb->dspace = binp->alloc[0];
tcb->cmn.dspace = binp->alloc[0];
/* Re-initialize the task's initial state to account for the new PIC base */
up_initial_state(tcb);
up_initial_state(&tcb->cmn);
#endif
/* Assign the address environment to the task */
#ifdef CONFIG_ADDRENV
ret = up_addrenv_assign(binp->addrenv, tcb);
ret = up_addrenv_assign(binp->addrenv, &tcb->cmn);
if (ret < 0)
{
err = -ret;
@ -228,7 +228,7 @@ int exec_module(FAR const struct binary_s *binp)
/* Get the assigned pid before we start the task */
pid = tcb->pid;
pid = tcb->cmn.pid;
/* Then activate the task at the provided priority */
@ -244,11 +244,11 @@ int exec_module(FAR const struct binary_s *binp)
errout_with_stack:
#ifndef CONFIG_CUSTOM_STACK
tcb->stack_alloc_ptr = NULL;
sched_releasetcb(tcb);
tcb->cmn.stack_alloc_ptr = NULL;
sched_releasetcb(&tcb->cmn);
kfree(stack);
#else
sched_releasetcb(tcb);
sched_releasetcb(&tcb->cmn);
#endif
goto errout;

View File

@ -387,8 +387,9 @@ struct task_group_s
#endif
/* struct tcb_s ******************************************************************/
/* This is the common part of the task control block (TCB). Each task or thread
* is represented by a TCB. The TCB is the heart of the NuttX task-control logic.
/* This is the common part of the task control block (TCB). The TCB is the heart
* of the NuttX task-control logic. Each task or thread is represented by a TCB
* that includes these common definitions.
*/
struct tcb_s
@ -419,12 +420,6 @@ struct tcb_s
start_t start; /* Thread start function */
entry_t entry; /* Entry Point into the thread */
#ifdef CONFIG_SCHED_STARTHOOK
starthook_t starthook; /* Task startup function */
FAR void *starthookarg; /* The argument passed to the function */
#endif
uint8_t sched_priority; /* Current priority of the thread */
#ifdef CONFIG_PRIORITY_INHERITANCE
@ -439,19 +434,10 @@ struct tcb_s
uint16_t flags; /* Misc. general status flags */
int16_t lockcount; /* 0=preemptable (not-locked) */
#ifndef CONFIG_DISABLE_PTHREAD
FAR void *joininfo; /* Detach-able info to support join */
#endif
#if CONFIG_RR_INTERVAL > 0
int timeslice; /* RR timeslice interval remaining */
#endif
/* Values needed to restart a task ********************************************/
uint8_t init_priority; /* Initial priority of the task */
char *argv[CONFIG_MAX_TASK_ARGS+1]; /* Name+start-up parameters */
/* Stack-Related Fields *******************************************************/
#ifndef CONFIG_CUSTOM_STACK
@ -470,12 +456,6 @@ struct tcb_s
FAR struct dspace_s *dspace; /* Allocated area for .bss and .data */
#endif
/* POSIX Thread Specific Data *************************************************/
#if !defined(CONFIG_DISABLE_PTHREAD) && CONFIG_NPTHREAD_KEYS > 0
FAR void *pthread_data[CONFIG_NPTHREAD_KEYS];
#endif
/* POSIX Semaphore Control Fields *********************************************/
sem_t *waitsem; /* Semaphore ID waiting on */
@ -512,6 +492,65 @@ struct tcb_s
#endif
};
/* struct task_tcb_s *************************************************************/
/* This is the particular form of the task control block (TCB) structure used by
* tasks (and kernel threads). There are two TCB forms: one for pthreads and
* one for tasks. Both share the common TCB fields (which must appear at the
* top of the structure) plus additional fields unique to tasks and threads.
* Having separate structures for tasks and pthreads adds some complexity, but
* saves memory in that it prevents pthreads from being burdened with the
* overhead required for tasks (and vice versa).
*/
struct task_tcb_s
{
/* Common TCB fields **********************************************************/
struct tcb_s cmn; /* Common TCB fields */
/* Task Management Fields *****************************************************/
#ifdef CONFIG_SCHED_STARTHOOK
starthook_t starthook; /* Task startup function */
FAR void *starthookarg; /* The argument passed to the function */
#endif
/* Values needed to restart a task ********************************************/
uint8_t init_priority; /* Initial priority of the task */
char *argv[CONFIG_MAX_TASK_ARGS+1]; /* Name+start-up parameters */
};
/* struct pthread_tcb_s **********************************************************/
/* This is the particular form of the task control block (TCB) structure used by
* pthreads. There are two TCB forms: one for pthreads and one for tasks. Both
* share the common TCB fields (which must appear at the top of the structure)
* plus additional fields unique to tasks and threads. Having separate structures
* for tasks and pthreads adds some complexity, but saves memory in that it
* prevents pthreads from being burdened with the overhead required for tasks
* (and vice versa).
*/
#ifndef CONFIG_DISABLE_PTHREAD
struct pthread_tcb_s
{
/* Common TCB fields **********************************************************/
struct tcb_s cmn; /* Common TCB fields */
/* Task Management Fields *****************************************************/
pthread_addr_t arg; /* Startup argument */
FAR void *joininfo; /* Detach-able info to support join */
/* POSIX Thread Specific Data *************************************************/
#if CONFIG_NPTHREAD_KEYS > 0
FAR void *pthread_data[CONFIG_NPTHREAD_KEYS];
#endif
};
#endif /* !CONFIG_DISABLE_PTHREAD */
/* This is the callback type used by sched_foreach() */
typedef void (*sched_foreach_t)(FAR struct tcb_s *tcb, FAR void *arg);
@ -556,7 +595,7 @@ FAR struct socketlist *sched_getsockets(void);
/* Setup up a start hook */
#ifdef CONFIG_SCHED_STARTHOOK
void task_starthook(FAR struct tcb_s *tcb, starthook_t starthook, FAR void *arg);
void task_starthook(FAR struct task_tcb_s *tcb, starthook_t starthook, FAR void *arg);
#endif
/* Internal vfork support.The overall sequence is:

View File

@ -122,10 +122,10 @@ void group_removechildren(FAR struct task_group_s *group);
/* Group data resource configuration */
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
int group_setupidlefiles(FAR struct tcb_s *tcb);
int group_setuptaskfiles(FAR struct tcb_s *tcb);
int group_setupidlefiles(FAR struct task_tcb_s *tcb);
int group_setuptaskfiles(FAR struct task_tcb_s *tcb);
#if CONFIG_NFILE_STREAMS > 0
int group_setupstreams(FAR struct tcb_s *tcb);
int group_setupstreams(FAR struct task_tcb_s *tcb);
#endif
#endif

View File

@ -78,10 +78,10 @@
*
****************************************************************************/
int group_setupidlefiles(FAR struct tcb_s *tcb)
int group_setupidlefiles(FAR struct task_tcb_s *tcb)
{
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0
FAR struct task_group_s *group = tcb->group;
FAR struct task_group_s *group = tcb->cmn.group;
#endif
#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_DEV_CONSOLE)
int fd;

View File

@ -72,13 +72,13 @@
*
****************************************************************************/
int group_setupstreams(FAR struct tcb_s *tcb)
int group_setupstreams(FAR struct task_tcb_s *tcb)
{
DEBUGASSERT(tcb && tcb->group);
DEBUGASSERT(tcb && tcb->cmn.group);
/* Initialize file streams for the task group */
lib_streaminit(&tcb->group->tg_streamlist);
lib_streaminit(&tcb->cmn.group->tg_streamlist);
/* fdopen to get the stdin, stdout and stderr streams. The following logic
* depends on the fact that the library layer will allocate FILEs in order.
@ -88,9 +88,9 @@ int group_setupstreams(FAR struct tcb_s *tcb)
* fd = 2 is stderr (write-only, append)
*/
(void)fs_fdopen(0, O_RDONLY, tcb);
(void)fs_fdopen(1, O_WROK|O_CREAT, tcb);
(void)fs_fdopen(2, O_WROK|O_CREAT, tcb);
(void)fs_fdopen(0, O_RDONLY, (FAR struct tcb_s *)tcb);
(void)fs_fdopen(1, O_WROK|O_CREAT, (FAR struct tcb_s *)tcb);
(void)fs_fdopen(2, O_WROK|O_CREAT, (FAR struct tcb_s *)tcb);
return OK;
}

View File

@ -85,7 +85,7 @@
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_FDCLONE_DISABLE)
static inline void sched_dupfiles(FAR struct tcb_s *tcb)
static inline void sched_dupfiles(FAR struct task_tcb_s *tcb)
{
/* The parent task is the one at the head of the ready-to-run list */
@ -94,7 +94,7 @@ static inline void sched_dupfiles(FAR struct tcb_s *tcb)
FAR struct file *child;
int i;
DEBUGASSERT(tcb && tcb->group && rtcb->group);
DEBUGASSERT(tcb && tcb->cmn.group && rtcb->group);
/* Duplicate the file descriptors. This will be either all of the
* file descriptors or just the first three (stdin, stdout, and stderr)
@ -105,7 +105,7 @@ static inline void sched_dupfiles(FAR struct tcb_s *tcb)
/* Get pointers to the parent and child task file lists */
parent = rtcb->group->tg_filelist.fl_files;
child = tcb->group->tg_filelist.fl_files;
child = tcb->cmn.group->tg_filelist.fl_files;
/* Check each file in the parent file list */
@ -143,7 +143,7 @@ static inline void sched_dupfiles(FAR struct tcb_s *tcb)
****************************************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0 && !defined(CONFIG_SDCLONE_DISABLE)
static inline void sched_dupsockets(FAR struct tcb_s *tcb)
static inline void sched_dupsockets(FAR struct task_tcb_s *tcb)
{
/* The parent task is the one at the head of the ready-to-run list */
@ -156,12 +156,12 @@ static inline void sched_dupsockets(FAR struct tcb_s *tcb)
* task.
*/
DEBUGASSERT(tcb && tcb->group && rtcb->group);
DEBUGASSERT(tcb && tcb->cmn.group && rtcb->group);
/* Get pointers to the parent and child task socket lists */
parent = rtcb->group->tg_socketlist.sl_sockets;
child = tcb->group->tg_socketlist.sl_sockets;
child = tcb->cmn.group->tg_socketlist.sl_sockets;
/* Check each socket in the parent socket list */
@ -206,13 +206,16 @@ static inline void sched_dupsockets(FAR struct tcb_s *tcb)
*
****************************************************************************/
int group_setuptaskfiles(FAR struct tcb_s *tcb)
int group_setuptaskfiles(FAR struct task_tcb_s *tcb)
{
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
FAR struct task_group_s *group = tcb->group;
FAR struct task_group_s *group = tcb->cmn.group;
DEBUGASSERT(group);
#endif
#ifndef CONFIG_DISABLE_PTHREAD
DEBUGASSERT((tcb->cmn.flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD);
#endif
#if CONFIG_NFILE_DESCRIPTORS > 0
/* Initialize file descriptors for the TCB */

View File

@ -257,9 +257,9 @@ int os_bringup(void);
void weak_function task_initialize(void);
#endif
void task_start(void);
int task_schedsetup(FAR struct tcb_s *tcb, int priority, start_t start,
int task_schedsetup(FAR struct task_tcb_s *tcb, int priority, start_t start,
main_t main, uint8_t ttype);
int task_argsetup(FAR struct tcb_s *tcb, FAR const char *name, FAR char * const argv[]);
int task_argsetup(FAR struct task_tcb_s *tcb, FAR const char *name, FAR char * const argv[]);
void task_exithook(FAR struct tcb_s *tcb, int status);
int task_deletecurrent(void);

View File

@ -204,7 +204,7 @@ const tasklist_t g_tasklisttable[NUM_TASK_STATES] =
* that user init task is responsible for bringing up the rest of the system
*/
static FAR struct tcb_s g_idletcb;
static FAR struct task_tcb_s g_idletcb;
/* This is the name of the idle task */
@ -262,7 +262,7 @@ void os_start(void)
/* Assign the process ID of ZERO to the idle task */
g_pidhash[ PIDHASH(0)].tcb = &g_idletcb;
g_pidhash[ PIDHASH(0)].tcb = &g_idletcb.cmn;
g_pidhash[ PIDHASH(0)].pid = 0;
/* Initialize a TCB for this thread of execution. NOTE: The default
@ -272,13 +272,13 @@ void os_start(void)
* that has pid == 0 and sched_priority == 0.
*/
bzero((void*)&g_idletcb, sizeof(struct tcb_s));
g_idletcb.task_state = TSTATE_TASK_RUNNING;
g_idletcb.entry.main = (main_t)os_start;
bzero((void*)&g_idletcb, sizeof(struct task_tcb_s));
g_idletcb.cmn.task_state = TSTATE_TASK_RUNNING;
g_idletcb.cmn.entry.main = (main_t)os_start;
#if CONFIG_TASK_NAME_SIZE > 0
strncpy(g_idletcb.name, g_idlename, CONFIG_TASK_NAME_SIZE-1);
g_idletcb.argv[0] = g_idletcb.name;
strncpy(g_idletcb.cmn.name, g_idlename, CONFIG_TASK_NAME_SIZE-1);
g_idletcb.argv[0] = g_idletcb.cmn.name;
#else
g_idletcb.argv[0] = (char*)g_idlename;
#endif /* CONFIG_TASK_NAME_SIZE */
@ -289,7 +289,7 @@ void os_start(void)
/* Initialize the processor-specific portion of the TCB */
up_initial_state(&g_idletcb);
up_initial_state(&g_idletcb.cmn);
/* Initialize the semaphore facility(if in link). This has to be done
* very early because many subsystems depend upon fully functional
@ -330,7 +330,7 @@ void os_start(void)
/* Allocate the IDLE group and suppress child status. */
#ifdef HAVE_TASK_GROUP
(void)group_allocate(&g_idletcb);
(void)group_allocate(&g_idletcb.cmn);
#endif
/* Initialize the interrupt handling subsystem (if included) */
@ -456,8 +456,8 @@ void os_start(void)
*/
#ifdef HAVE_TASK_GROUP
(void)group_initialize(&g_idletcb);
g_idletcb.group->tg_flags = GROUP_FLAG_NOCLDWAIT;
(void)group_initialize(&g_idletcb.cmn);
g_idletcb.cmn.group->tg_flags = GROUP_FLAG_NOCLDWAIT;
#endif
/* Create initial tasks and bring-up the system */

View File

@ -99,48 +99,26 @@ static const char g_pthreadname[] = "<pthread>";
*
* Input Parameters:
* tcb - Address of the new task's TCB
* name - Name of the new task (not used)
* argv - A pointer to an array of input parameters. Up to
* CONFIG_MAX_TASK_ARG parameters may be provided. If fewer
* than CONFIG_MAX_TASK_ARG parameters are passed, the list
* should be terminated with a NULL argv[] value. If no
* parameters are required, argv may be NULL.
* arg - The argument to provide to the pthread on startup.
*
* Return Value:
* None
*
****************************************************************************/
static void pthread_argsetup(FAR struct tcb_s *tcb, pthread_addr_t arg)
static inline void pthread_argsetup(FAR struct pthread_tcb_s *tcb, pthread_addr_t arg)
{
int i;
#if CONFIG_TASK_NAME_SIZE > 0
/* Copy the pthread name into the TCB */
strncpy(tcb->name, g_pthreadname, CONFIG_TASK_NAME_SIZE);
/* Save the name as the first argument in the TCB */
tcb->argv[0] = tcb->name;
#else
/* Save the name as the first argument in the TCB */
tcb->argv[0] = (char *)g_pthreadname;
strncpy(tcb->cmn.name, g_pthreadname, CONFIG_TASK_NAME_SIZE);
#endif /* CONFIG_TASK_NAME_SIZE */
/* For pthreads, args are strictly pass-by-value; that actual
* type wrapped by pthread_addr_t is unknown.
*/
tcb->argv[1] = (char*)arg;
/* Nullify the remaining, unused argument storage */
for (i = 2; i < CONFIG_MAX_TASK_ARGS+1; i++)
{
tcb->argv[i] = NULL;
}
tcb->arg = arg;
}
/****************************************************************************
@ -189,8 +167,8 @@ static inline void pthread_addjoininfo(FAR struct task_group_s *group,
static void pthread_start(void)
{
FAR struct tcb_s *ptcb = (FAR struct tcb_s*)g_readytorun.head;
FAR struct task_group_s *group = ptcb->group;
FAR struct pthread_tcb_s *ptcb = (FAR struct pthread_tcb_s*)g_readytorun.head;
FAR struct task_group_s *group = ptcb->cmn.group;
FAR struct join_s *pjoin = (FAR struct join_s*)ptcb->joininfo;
pthread_addr_t exit_status;
@ -214,7 +192,7 @@ static void pthread_start(void)
* available to the pthread.
*/
exit_status = (*ptcb->entry.pthread)((pthread_addr_t)ptcb->argv[1]);
exit_status = (*ptcb->cmn.entry.pthread)(ptcb->arg);
/* The thread has returned */
@ -247,7 +225,7 @@ static void pthread_start(void)
int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
pthread_startroutine_t start_routine, pthread_addr_t arg)
{
FAR struct tcb_s *ptcb;
FAR struct pthread_tcb_s *ptcb;
FAR struct join_s *pjoin;
int priority;
#if CONFIG_RR_INTERVAL > 0
@ -266,7 +244,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
/* Allocate a TCB for the new task. */
ptcb = (FAR struct tcb_s*)kzalloc(sizeof(struct tcb_s));
ptcb = (FAR struct pthread_tcb_s *)kzalloc(sizeof(struct pthread_tcb_s));
if (!ptcb)
{
return ENOMEM;
@ -277,7 +255,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
*/
#ifdef HAVE_TASK_GROUP
ret = group_bind(ptcb);
ret = group_bind((FAR struct tcb_s *)ptcb);
if (ret < 0)
{
errcode = ENOMEM;
@ -291,7 +269,8 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
*/
#ifdef CONFIG_ADDRENV
ret = up_addrenv_share((FAR const struct tcb_s *)g_readytorun.head, ptcb);
ret = up_addrenv_share((FAR const struct tcb_s *)g_readytorun.head,
(FAR struct tcb_s *)ptcb);
if (ret < 0)
{
errcode = -ret;
@ -310,7 +289,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
/* Allocate the stack for the TCB */
ret = up_create_stack(ptcb, attr->stacksize);
ret = up_create_stack((FAR struct tcb_s *)ptcb, attr->stacksize);
if (ret != OK)
{
errcode = ENOMEM;
@ -359,8 +338,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
/* Initialize the task control block */
ret = task_schedsetup(ptcb, priority, pthread_start, (main_t)start_routine,
TCB_FLAG_TTYPE_PTHREAD);
ret = pthread_schedsetup(ptcb, priority, pthread_start, start_routine);
if (ret != OK)
{
errcode = EBUSY;
@ -376,7 +354,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
/* Join the parent's task group */
#ifdef HAVE_TASK_GROUP
ret = group_join(ptcb);
ret = group_join((FAR struct tcb_s *)ptcb);
if (ret < 0)
{
errcode = ENOMEM;
@ -386,7 +364,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
/* Attach the join info to the TCB. */
ptcb->joininfo = (void*)pjoin;
ptcb->joininfo = (FAR void *)pjoin;
/* If round robin scheduling is selected, set the appropriate flag
* in the TCB.
@ -405,7 +383,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
* as well.
*/
pid = (int)ptcb->pid;
pid = (int)ptcb->cmn.pid;
pjoin->thread = (pthread_t)pid;
/* Initialize the semaphores in the join structure to zero. */
@ -421,7 +399,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
sched_lock();
if (ret == OK)
{
ret = task_activate(ptcb);
ret = task_activate((FAR struct tcb_s *)ptcb);
}
if (ret == OK)
@ -465,6 +443,6 @@ errout_with_join:
ptcb->joininfo = NULL;
errout_with_tcb:
sched_releasetcb(ptcb);
sched_releasetcb((FAR struct tcb_s *)ptcb);
return errcode;
}

View File

@ -104,11 +104,12 @@
FAR void *pthread_getspecific(pthread_key_t key)
{
#if CONFIG_NPTHREAD_KEYS > 0
FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;
FAR struct task_group_s *group = rtcb->group;
FAR struct pthread_tcb_s *rtcb = (FAR struct pthread_tcb_s*)g_readytorun.head;
FAR struct task_group_s *group = rtcb->cmn.group;
FAR void *ret = NULL;
DEBUGASSERT(group);
DEBUGASSERT(group &&
(rtcb->cmn.flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD);
/* Check if the key is valid. */

View File

@ -46,6 +46,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>
#include <sched.h>
#include <nuttx/compiler.h>
@ -96,6 +97,8 @@ extern "C"
struct task_group_s; /* Forward reference */
void weak_function pthread_initialize(void);
int pthread_schedsetup(FAR struct tcb_s *tcb, int priority, start_t start,
pthread_startroutine_t entry);
int pthread_completejoin(pid_t pid, FAR void *exit_value);
void pthread_destroyjoin(FAR struct task_group_s *group,
FAR struct join_s *pjoin);

View File

@ -115,11 +115,12 @@
int pthread_setspecific(pthread_key_t key, FAR void *value)
{
#if CONFIG_NPTHREAD_KEYS > 0
FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;
FAR struct task_group_s *group = rtcb->group;
FAR struct pthread_tcb_s *rtcb = (FAR struct pthread_tcb_s*)g_readytorun.head;
FAR struct task_group_s *group = rtcb->cmn.group;
int ret = EINVAL;
DEBUGASSERT(group);
DEBUGASSERT(group &&
(rtcb->cmn.flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD);
/* Check if the key is valid. */

View File

@ -155,11 +155,14 @@ int sched_releasetcb(FAR struct tcb_s *tcb)
* start/re-start.
*/
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
#ifndef CONFIG_DISABLE_PTHREAD
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD)
#endif
{
for (i = 1; i < CONFIG_MAX_TASK_ARGS+1 && tcb->argv[i]; i++)
FAR struct task_tcb_s *ttcb = (FAR struct task_tcb_s *)tcb;
for (i = 1; i < CONFIG_MAX_TASK_ARGS+1 && ttcb->argv[i]; i++)
{
sched_free((FAR void*)tcb->argv[i]);
sched_free((FAR void*)ttcb->argv[i]);
}
}

View File

@ -106,14 +106,14 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
main_t entry, FAR char * const argv[])
#endif
{
FAR struct tcb_s *tcb;
FAR struct task_tcb_s *tcb;
pid_t pid;
int errcode;
int ret;
/* Allocate a TCB for the new task. */
tcb = (FAR struct tcb_s*)kzalloc(sizeof(struct tcb_s));
tcb = (FAR struct task_tcb_s *)kzalloc(sizeof(struct task_tcb_s));
if (!tcb)
{
errcode = ENOMEM;
@ -123,7 +123,7 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
/* Allocate a new task group */
#ifdef HAVE_TASK_GROUP
ret = group_allocate(tcb);
ret = group_allocate((FAR struct tcb_s *)tcb);
if (ret < 0)
{
errcode = -ret;
@ -145,7 +145,7 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
/* Allocate the stack for the TCB */
#ifndef CONFIG_CUSTOM_STACK
ret = up_create_stack(tcb, stack_size);
ret = up_create_stack((FAR struct tcb_s *)tcb, stack_size);
if (ret != OK)
{
errcode = -ret;
@ -169,7 +169,7 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
/* Now we have enough in place that we can join the group */
#ifdef HAVE_TASK_GROUP
ret = group_initialize(tcb);
ret = group_initialize((FAR struct tcb_s *)tcb);
if (ret < 0)
{
errcode = -ret;
@ -179,11 +179,11 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
/* Get the assigned pid before we start the task */
pid = (int)tcb->pid;
pid = (int)tcb->cmn.pid;
/* Activate the task */
ret = task_activate(tcb);
ret = task_activate((FAR struct tcb_s *)tcb);
if (ret != OK)
{
errcode = get_errno();
@ -197,7 +197,7 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
return pid;
errout_with_tcb:
sched_releasetcb(tcb);
sched_releasetcb((FAR struct tcb_s *)tcb);
errout:
set_errno(errcode);

View File

@ -318,7 +318,9 @@ static inline void task_sigchild(gid_t pgid, FAR struct tcb_s *ctcb, int status)
* interpretable exit Check if this is the main task that is exiting.
*/
if ((ctcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
#ifndef CONFIG_DISABLE_PTHREAD
if ((ctcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD)
#endif
{
task_exitstatus(pgrp, status);
}
@ -363,7 +365,9 @@ static inline void task_sigchild(FAR struct tcb_s *ptcb, FAR struct tcb_s *ctcb,
* that are still running.
*/
if ((ctcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
#ifndef CONFIG_DISABLE_PTHREAD
if ((ctcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD)
#endif
{
#ifdef CONFIG_SCHED_CHILD_STATUS
/* Save the exit status now of the main thread */
@ -480,11 +484,14 @@ static inline void task_exitwakeup(FAR struct tcb_s *tcb, int status)
if (group)
{
/* Only tasks return valid status. Record the exit status when the
* task exists. The group, however, may still be executing.
/* Only tasks (and kernel threads) return valid status. Record the
* exit status when the task exists. The group, however, may still
* be executing.
*/
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
#ifndef CONFIG_DISABLE_PTHREAD
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD)
#endif
{
/* Report the exit status. We do not nullify tg_statloc here
* because we want to prent other tasks from registering for

View File

@ -120,9 +120,17 @@ int task_init(FAR struct tcb_s *tcb, const char *name, int priority,
main_t entry, FAR char * const argv[])
#endif
{
FAR struct task_tcb_s *ttcb = (FAR struct task_tcb_s *)tcb;
int errcode;
int ret;
/* Only tasks and kernel threads can be initialized in this way */
#ifndef CONFIG_DISABLE_PTHREAD
DEBUGASSERT(tcb &&
(tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD);
#endif
/* Create a new task group */
#ifdef HAVE_TASK_GROUP
@ -137,7 +145,7 @@ int task_init(FAR struct tcb_s *tcb, const char *name, int priority,
/* Associate file descriptors with the new task */
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
ret = group_setuptaskfiles(tcb);
ret = group_setuptaskfiles(ttcb);
if (ret < 0)
{
errcode = -ret;
@ -153,7 +161,7 @@ int task_init(FAR struct tcb_s *tcb, const char *name, int priority,
/* Initialize the task control block */
ret = task_schedsetup(tcb, priority, task_start, entry,
ret = task_schedsetup(ttcb, priority, task_start, entry,
TCB_FLAG_TTYPE_TASK);
if (ret < OK)
{
@ -163,7 +171,7 @@ int task_init(FAR struct tcb_s *tcb, const char *name, int priority,
/* Setup to pass parameters to the new task */
(void)task_argsetup(tcb, name, argv);
(void)task_argsetup(ttcb, name, argv);
/* Now we have enough in place that we can join the group */

View File

@ -1,7 +1,7 @@
/****************************************************************************
* sched/task_restart.c
*
* Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2007, 2009, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -38,9 +38,13 @@
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <sched.h>
#include <errno.h>
#include <nuttx/arch.h>
#include "os_internal.h"
#include "sig_internal.h"
@ -97,7 +101,7 @@
int task_restart(pid_t pid)
{
FAR struct tcb_s *rtcb;
FAR struct tcb_s *tcb;
FAR struct task_tcb_s *tcb;
irqstate_t state;
int status;
@ -109,11 +113,12 @@ int task_restart(pid_t pid)
/* Check if the task to restart is the calling task */
rtcb = (FAR struct tcb_s*)g_readytorun.head;
rtcb = (FAR struct tcb_s *)g_readytorun.head;
if ((pid == 0) || (pid == rtcb->pid))
{
/* Not implemented */
set_errno(ENOSYS);
return ERROR;
}
@ -123,11 +128,18 @@ int task_restart(pid_t pid)
{
/* Find for the TCB associated with matching pid */
tcb = sched_gettcb(pid);
tcb = (FAR struct task_tcb_s *)sched_gettcb(pid);
#ifndef CONFIG_DISABLE_PTHREAD
if (!tcb || (tcb->cmn.flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
#else
if (!tcb)
#endif
{
/* There is no TCB with this pid */
/* There is no TCB with this pid or, if there is, it is not a
* task.
*/
set_errno(ESRCH);
return ERROR;
}
@ -136,24 +148,25 @@ int task_restart(pid_t pid)
*/
state = irqsave();
dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)g_tasklisttable[tcb->task_state].list);
tcb->task_state = TSTATE_TASK_INVALID;
dq_rem((FAR dq_entry_t*)tcb,
(dq_queue_t*)g_tasklisttable[tcb->cmn.task_state].list);
tcb->cmn.task_state = TSTATE_TASK_INVALID;
irqrestore(state);
/* Deallocate anything left in the TCB's queues */
sig_cleanup(tcb); /* Deallocate Signal lists */
sig_cleanup((FAR struct tcb_s *)tcb); /* Deallocate Signal lists */
/* Reset the current task priority */
tcb->sched_priority = tcb->init_priority;
tcb->cmn.sched_priority = tcb->init_priority;
/* Reset the base task priority and the number of pending reprioritizations */
#ifdef CONFIG_PRIORITY_INHERITANCE
tcb->base_priority = tcb->init_priority;
tcb->cmn.base_priority = tcb->init_priority;
# if CONFIG_SEM_NNESTPRIO > 0
tcb->npend_reprio = 0;
tcb->npend_reprio = 0;
# endif
#endif
@ -161,20 +174,20 @@ int task_restart(pid_t pid)
* This will reset the entry point and the start-up parameters
*/
up_initial_state(tcb);
up_initial_state((FAR struct tcb_s *)tcb);
/* Add the task to the inactive task list */
dq_addfirst((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks);
tcb->task_state = TSTATE_TASK_INACTIVE;
tcb->cmn.task_state = TSTATE_TASK_INACTIVE;
/* Activate the task */
status = task_activate(tcb);
status = task_activate((FAR struct tcb_s *)tcb);
if (status != OK)
{
dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks);
sched_releasetcb(tcb);
sched_releasetcb((FAR struct tcb_s *)tcb);
return ERROR;
}
}

View File

@ -49,6 +49,7 @@
#include <nuttx/arch.h>
#include "os_internal.h"
#include "pthread_internal.h"
#include "group_internal.h"
/****************************************************************************
@ -183,7 +184,9 @@ static inline void task_saveparent(FAR struct tcb_s *tcb, uint8_t ttype)
* the same task group.
*/
#ifndef CONFIG_DISABLE_PTHREAD
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD)
#endif
{
/* This is a new task in a new task group, we have to copy the ID from
* the parent's task group structure to child's task group.
@ -290,24 +293,20 @@ static inline void task_dupdspace(FAR struct tcb_s *tcb)
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: task_schedsetup
* Name: thread_schedsetup
*
* Description:
* This functions initializes a Task Control Block (TCB) in preparation
* for starting a new thread.
* This functions initializes the common portions of the Task Control Block
* (TCB) in preparation for starting a new thread.
*
* task_schedsetup() is called from task_init(), task_start(), and
* pthread_create();
* thread_schedsetup() is called from task_schedsetup() and
* pthread_schedsetup().
*
* Input Parameters:
* tcb - Address of the new task's TCB
* priority - Priority of the new task
* entry - Entry point of a new task
* main - Application start point of the new task
* start - Thread startup rotuine
* entry - Thred user entry point
* ttype - Type of the new thread: task, pthread, or kernel thread
*
* Return Value:
@ -318,8 +317,8 @@ static inline void task_dupdspace(FAR struct tcb_s *tcb)
*
****************************************************************************/
int task_schedsetup(FAR struct tcb_s *tcb, int priority, start_t start, main_t main,
uint8_t ttype)
static int thread_schedsetup(FAR struct tcb_s *tcb, int priority,
start_t start, FAR void *entry, uint8_t ttype)
{
int ret;
@ -330,13 +329,12 @@ int task_schedsetup(FAR struct tcb_s *tcb, int priority, start_t start, main_t m
{
/* Save task priority and entry point in the TCB */
tcb->init_priority = (uint8_t)priority;
tcb->sched_priority = (uint8_t)priority;
#ifdef CONFIG_PRIORITY_INHERITANCE
tcb->base_priority = (uint8_t)priority;
#endif
tcb->start = start;
tcb->entry.main = main;
tcb->entry.main = (main_t)entry;
/* Save the thrad type. This setting will be needed in
* up_initial_state() is called.
@ -388,6 +386,88 @@ int task_schedsetup(FAR struct tcb_s *tcb, int priority, start_t start, main_t m
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: task_schedsetup
*
* Description:
* This functions initializes a Task Control Block (TCB) in preparation
* for starting a new task.
*
* task_schedsetup() is called from task_init() and task_start().
*
* Input Parameters:
* tcb - Address of the new task's TCB
* priority - Priority of the new task
* start - Startup function (probably task_start())
* main - Application start point of the new task
* ttype - Type of the new thread: task or kernel thread
*
* Return Value:
* OK on success; ERROR on failure.
*
* This function can only failure is it is unable to assign a new, unique
* task ID to the TCB (errno is not set).
*
****************************************************************************/
int task_schedsetup(FAR struct task_tcb_s *tcb, int priority, start_t start,
main_t main, uint8_t ttype)
{
int ret;
/* Perform common thread setup */
ret = thread_schedsetup((FAR struct tcb_s *)tcb, priority, start,
(FAR void *)main, ttype);
if (ret == OK)
{
/* Save task restart priority */
tcb->init_priority = (uint8_t)priority;
}
return ret;
}
/****************************************************************************
* Name: pthread_schedsetup
*
* Description:
* This functions initializes a Task Control Block (TCB) in preparation
* for starting a new pthread.
*
* pthread_schedsetup() is called from pthread_create(),
*
* Input Parameters:
* tcb - Address of the new task's TCB
* priority - Priority of the new task
* start - Startup function (probably pthread_start())
* entry - Entry point of the new pthread
* ttype - Type of the new thread: task, pthread, or kernel thread
*
* Return Value:
* OK on success; ERROR on failure.
*
* This function can only failure is it is unable to assign a new, unique
* task ID to the TCB (errno is not set).
*
****************************************************************************/
#ifndef CONFIG_DISABLE_PTHREAD
int pthread_schedsetup(FAR struct tcb_s *tcb, int priority, start_t start,
pthread_startroutine_t entry)
{
/* Perform common thread setup */
return thread_schedsetup(tcb, priority, start, (FAR void *)entry,
TCB_FLAG_TTYPE_PTHREAD);
}
#endif
/****************************************************************************
* Name: task_argsetup
*
@ -414,7 +494,8 @@ int task_schedsetup(FAR struct tcb_s *tcb, int priority, start_t start, main_t m
*
****************************************************************************/
int task_argsetup(FAR struct tcb_s *tcb, const char *name, FAR char * const argv[])
int task_argsetup(FAR struct task_tcb_s *tcb, const char *name,
FAR char * const argv[])
{
int i;
@ -423,16 +504,16 @@ int task_argsetup(FAR struct tcb_s *tcb, const char *name, FAR char * const argv
if (!name)
{
name = (char *)g_noname;
name = (FAR char *)g_noname;
}
/* Copy the name into the TCB */
strncpy(tcb->name, name, CONFIG_TASK_NAME_SIZE);
strncpy(tcb->cmn.name, name, CONFIG_TASK_NAME_SIZE);
/* Save the name as the first argument */
tcb->argv[0] = tcb->name;
tcb->argv[0] = tcb->cmn.name;
#else
/* Save the name as the first argument */

View File

@ -1,7 +1,7 @@
/****************************************************************************
* sched/task_start.c
*
* Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2010, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -91,9 +91,11 @@
void task_start(void)
{
FAR struct tcb_s *tcb = (FAR struct tcb_s*)g_readytorun.head;
FAR struct task_tcb_s *tcb = (FAR struct task_tcb_s*)g_readytorun.head;
int argc;
DEBUGASSERT((tcb->cmn.flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD);
/* Execute the start hook if one has been registered */
#ifdef CONFIG_SCHED_STARTHOOK
@ -119,5 +121,5 @@ void task_start(void)
* the task returns.
*/
exit(tcb->entry.main(argc, tcb->argv));
exit(tcb->cmn.entry.main(argc, tcb->argv));
}

View File

@ -1,7 +1,7 @@
/****************************************************************************
* sched/task_start.c
* sched/task_starthook.c
*
* Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -90,9 +90,20 @@
*
****************************************************************************/
void task_starthook(FAR struct tcb_s *tcb, starthook_t starthook, FAR void *arg)
void task_starthook(FAR struct task_tcb_s *tcb, starthook_t starthook,
FAR void *arg)
{
DEBUGASSERT(tcb);
/* Only tasks can have starthooks. The starthook will be called when the
* task is started (or restarted).
*/
#ifndef CONFIG_DISABLE_PTHREAD
DEBUGASSERT(tcb &&
(tcb->cmn.flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD);
#endif
/* Set up the start hook */
tcb->starthook = starthook;
tcb->starthookarg = arg;
}

View File

@ -108,7 +108,7 @@
FAR struct tcb_s *task_vforksetup(start_t retaddr)
{
struct tcb_s *parent = (FAR struct tcb_s *)g_readytorun.head;
struct tcb_s *child;
struct task_tcb_s *child;
int priority;
int ret;
@ -116,7 +116,7 @@ FAR struct tcb_s *task_vforksetup(start_t retaddr)
/* Allocate a TCB for the child task. */
child = (FAR struct tcb_s*)kzalloc(sizeof(struct tcb_s));
child = (FAR struct task_tcb_s *)kzalloc(sizeof(struct task_tcb_s));
if (!child)
{
set_errno(ENOMEM);
@ -152,10 +152,10 @@ FAR struct tcb_s *task_vforksetup(start_t retaddr)
}
svdbg("parent=%p, returning child=%p\n", parent, child);
return child;
return (FAR struct tcb_s *)child;
errout_with_tcb:
sched_releasetcb(child);
sched_releasetcb((FAR struct tcb_s *)child);
set_errno(-ret);
return NULL;
}