summaryrefslogtreecommitdiffstats
path: root/nuttx/sched/os_internal.h
blob: a54157cd81e9a2149a1de299bac4f9910c05f109 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/************************************************************
 * os_internal.h
 *
 *   Copyright (C) 2007 Gregory Nutt. All rights reserved.
 *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name Gregory Nutt nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ************************************************************/

#ifndef __OS_INTERNAL_H
#define __OS_INTERNAL_H

/************************************************************
 * Included Files
 ************************************************************/

#include <queue.h>
#include <sched.h>
#include <nuttx/kmalloc.h>

/************************************************************
 * Definitions
 ************************************************************/

/* OS CRASH CODES */

enum os_crash_codes_e
{
  OSERR_NOERROR = 0,          /* No error */
  OSERR_NOTIMPLEMENTED,       /* Feature is not implemented */
  OSERR_INTERNAL,             /* Internal logic error */
  OSERR_UNEXPECTEDISR,        /* Received unexpected interrupt */
  OSERR_UNDEFINEDINSN,        /* Undefined instruction */
  OSERR_ERREXCEPTION,         /* Other CPU-detected errors */
  OSERR_OUTOFMEMORY,          /* Insufficient memory */
  OSERR_OUTOFMESSAGES,        /* Out of messages */
  OSERR_NOIDLETASK,           /* There is no idle task */
  OSERR_MQNONEMPTYCOUNT,      /* Expected waiter for non-empty queue */
  OSERR_MQNOTFULLCOUNT,       /* Expected waiter for non-full queue */
  OSERR_BADWAITSEM,           /* Already waiting for a semaphore */
  OSERR_BADMSGTYPE,           /* Tried to free a bad message type */
  OSERR_FAILEDTOADDSIGNAL,    /* Failed to add pending signal */
  OSERR_FAILEDTOREMOVESIGNAL, /* Failed to remove pending signal */
  OSERR_TIMEOUTNOTCB,         /* Timed out, but not TCB registered */
  OSERR_NOPENDINGSIGNAL,      /* Expected a signal to be pending */
  OSERR_BADDELETESTATE,       /* Bad state in task deletion */
  OSERR_WDOGNOTFOUND,         /* Active watchdog not found */
  OSERR_EXITFROMINTERRUPT,    /* Interrupt code attempted to exit */
  OSERR_BADUNBLOCKSTATE,      /* Attempt to unblock from bad state */
  OSERR_BADBLOCKSTATE,        /* Attempt to block from bad state */
  OSERR_BADREPRIORITIZESTATE, /* Attempt to reprioritize in bad state or priority */
};

/* Special task IDS */

#define NULL_TASK_PROCESS_ID 0
#define INVALID_PROCESS_ID   0

/* Although task IDs can take the (positive, non-zero)
 * range of pid_t, the number of tasks that will be supported
 * at any one time is (artificially) limited by the CONFIG_MAX_TASKS
 * configuration setting. Limiting the number of tasks speeds certain
 * OS functions (this is the only limitation in the number of
 * tasks built into the design).
 */

#define MAX_TASKS_MASK      (CONFIG_MAX_TASKS-1)
#define PIDHASH(pid)        ((pid) & MAX_TASKS_MASK)

/* Stubs used when there are no file descriptors */

#if CONFIG_NFILE_DESCRIPTORS <= 0 && CONFIG_NSOCKET_DESCRIPTORS <= 0
# define sched_setupidlefiles(t)    (OK)
# define sched_setuptaskfiles(t)    (OK)
# define sched_setuppthreadfiles(t) (OK)
# define sched_releasefiles(t)      (OK)
#endif

/* A more efficient ways to access the errno */

#define SET_ERRNO(e) \
  { _TCB *rtcb = _TCB*)g_readytorun.head; rtcb->errno = (e); }

#define _SET_TCB_ERRNO(t,e) \
  { (t)->errno = (e); }

/************************************************************
 * 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.
 */

struct pidhash_s
{
  FAR _TCB *tcb;
  pid_t     pid;
};
typedef struct pidhash_s  pidhash_t;

/* This structure defines an element of the g_tasklisttable[].
 * This table is used to map a task_state enumeration to the
 * corresponding task list.
 */

struct tasklist_s
{
  DSEG volatile dq_queue_t *list; /* Pointer to the task list */
  boolean prioritized;            /* TRUE if the list is prioritized */
};
typedef struct tasklist_s tasklist_t;

/************************************************************
 * Global Variables
 ************************************************************/

/* Declared in os_start.c ***********************************/

/* The state of a task is indicated both by the task_state field
 * of the TCB and by a series of task lists.  All of these
 * tasks lists are declared below. Although it is not always
 * necessary, most of these lists are prioritized so that common
 * list handling logic can be used (only the g_readytorun,
 * the g_pendingtasks, and the g_waitingforsemaphore lists need
 * to be prioritized).
 */

/* This is the list of all tasks that are ready to run.  The head
 * of this list is the currently active task; the tail of this
 * list is always the idle task.
 */

extern volatile dq_queue_t g_readytorun;

/* This is the list of all tasks that are ready-to-run, but
 * cannot be placed in the g_readytorun list because:  (1) They
 * are higher priority than the currently active task at the head
 * of the g_readytorun list, and (2) the currenly active task has
 * disabled pre-emption.
 */

extern volatile dq_queue_t g_pendingtasks;

/* This is the list of all tasks that are blocked waiting for a semaphore */

extern volatile dq_queue_t g_waitingforsemaphore;

/* This is the list of all tasks that are blocked waiting for a signal */

#ifndef CONFIG_DISABLE_SIGNALS
extern volatile dq_queue_t g_waitingforsignal;
#endif

/* This is the list of all tasks that are blocked waiting for a message
 * queue to become non-empty.
 */

#ifndef CONFIG_DISABLE_MQUEUE
extern volatile dq_queue_t g_waitingformqnotempty;
#endif

/* This is the list of all tasks that are blocked waiting for a message
 * queue to become non-full.
 */

#ifndef CONFIG_DISABLE_MQUEUE
extern volatile dq_queue_t g_waitingformqnotfull;
#endif

/* This the list of all tasks that have been initialized, but not yet
 * activated. NOTE:  This is the only list that is not prioritized.
 */

extern volatile dq_queue_t g_inactivetasks;

/* This is the list of dayed memory deallocations that need to be handled
 * within the IDLE loop.  These deallocations get queued by sched_free()
 * if the OS attempts to deallocate memory while it is within an interrupt
 * handler.
 */

extern volatile sq_queue_t g_delayeddeallocations;

/* This is the value of the last process ID assigned to a task */

extern volatile pid_t g_lastpid;

/* The following hash table is used for two things:
 *
 * 1. This hash table greatly speeds the determination of
 *    a new unique process ID for a task, and
 * 2. Is used to quickly map a process ID into a TCB.
 *
 * It has the side effects of using more memory and limiting
 * the number of tasks to CONFIG_MAX_TASKS.
 */

extern pidhash_t g_pidhash[CONFIG_MAX_TASKS];

/* This is a table of task lists.  This table is indexed by
 * the task state enumeration type (tstate_t) and provides
 * a pointer to the associated static task list (if there
 * is one) as well as a boolean indication as to if the list
 * is an ordered list or not.
 */

extern const tasklist_t g_tasklisttable[NUM_TASK_STATES];

/************************************************************
 * Public Function Prototypes
 ************************************************************/

extern void    task_start(void);
extern STATUS  task_schedsetup(FAR _TCB *tcb, int priority,
                               start_t start, main_t main);
extern STATUS  task_argsetup(FAR _TCB *tcb, const char *name,
                             const char *argv[]);

extern boolean sched_addreadytorun(FAR _TCB *rtrtcb);
extern boolean sched_removereadytorun(FAR _TCB *rtrtcb);
extern boolean sched_addprioritized(FAR _TCB *newTcb,
                                    DSEG dq_queue_t *list);
extern boolean sched_mergepending(void);
extern void    sched_addblocked(FAR _TCB *btcb, tstate_t task_state);
extern void    sched_removeblocked(FAR _TCB *btcb);
extern FAR _TCB *sched_gettcb(pid_t pid);

#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
extern int     sched_setupidlefiles(FAR _TCB *tcb);
extern int     sched_setuptaskfiles(FAR _TCB *tcb);
extern int     sched_setuppthreadfiles(FAR _TCB *tcb);
#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0
extern int     sched_setupstreams(FAR _TCB *tcb);
extern int     sched_flushfiles(FAR _TCB *tcb);
#endif
extern int     sched_releasefiles(FAR _TCB *tcb);
#endif

extern int     sched_releasetcb(FAR _TCB *tcb);

#endif /* __OS_INTERNAL_H */