summaryrefslogtreecommitdiff
path: root/firmware/export/thread.h
blob: 17e6e3aa88231c5bba66fb7dadeff88af7095752 (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
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2002 by Ulf Ralberg
 *
 * All files in this archive are subject to the GNU General Public License.
 * See the file COPYING in the source tree root for full license agreement.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/
#ifndef THREAD_H
#define THREAD_H

#include "config.h"
#include <stdbool.h>

/* Priority scheduling (when enabled with HAVE_PRIORITY_SCHEDULING) works
 * by giving high priority threads more CPU time than less priority threads
 * when they need it.
 * 
 * If software playback codec pcm buffer is going down to critical, codec
 * can change it own priority to REALTIME to override user interface and
 * prevent playback skipping.
 */
#define PRIORITY_REALTIME        1
#define PRIORITY_USER_INTERFACE  4 /* The main thread */
#define PRIORITY_RECORDING       4 /* Recording thread */
#define PRIORITY_PLAYBACK        4 /* or REALTIME when needed */
#define PRIORITY_BUFFERING       4 /* Codec buffering thread */
#define PRIORITY_SYSTEM          6 /* All other firmware threads */
#define PRIORITY_BACKGROUND      8 /* Normal application threads */

#if CONFIG_CODEC == SWCODEC
#define MAXTHREADS	15
#else
#define MAXTHREADS  11
#endif

#define DEFAULT_STACK_SIZE 0x400 /* Bytes */

#ifndef SIMULATOR
/* Need to keep structures inside the header file because debug_menu
 * needs them. */
# ifdef CPU_COLDFIRE
struct regs
{
    unsigned int macsr;  /* EMAC status register */
    unsigned int d[6];   /* d2-d7 */
    unsigned int a[5];   /* a2-a6 */
    void         *sp;    /* Stack pointer (a7) */
    void         *start; /* Thread start address, or NULL when started */
};
# elif CONFIG_CPU == SH7034
struct regs
{
    unsigned int r[7];   /* Registers r8 thru r14 */
    void         *sp;    /* Stack pointer (r15) */
    void         *pr;    /* Procedure register */
    void         *start; /* Thread start address, or NULL when started */
};
# elif defined(CPU_ARM)
struct regs
{
    unsigned int r[8];   /* Registers r4-r11 */
    void         *sp;    /* Stack pointer (r13) */
    unsigned int lr;     /* r14 (lr) */
    void         *start; /* Thread start address, or NULL when started */
};
# elif CONFIG_CPU == TCC730
struct regs
{
    void *sp;    /* Stack pointer (a15) */
    void *start; /* Thread start address */
    int started; /* 0 when not started */
};
# endif

#endif /* !SIMULATOR */

#define STATE_RUNNING         0
#define STATE_BLOCKED         1
#define STATE_SLEEPING        2
#define STATE_BLOCKED_W_TMO   3

#define GET_STATE_ARG(state)  (state & 0x3FFFFFFF)
#define GET_STATE(state)      ((state >> 30) & 3)
#define SET_STATE(state,arg)  ((state << 30) | (arg))

struct thread_entry {
#ifndef SIMULATOR
    struct regs context;
#endif
    const char *name;
    void *stack;
    unsigned long statearg;
    unsigned short stack_size;
#ifdef HAVE_PRIORITY_SCHEDULING
    unsigned short priority;
    long last_run;
#endif
    struct thread_entry *next, *prev;
};

struct core_entry {
    struct thread_entry threads[MAXTHREADS];
    struct thread_entry *running;
    struct thread_entry *sleeping;
};

#ifdef HAVE_PRIORITY_SCHEDULING
#define IF_PRIO(empty, type)  , type
#else
#define IF_PRIO(empty, type)
#endif

struct thread_entry*
    create_thread(void (*function)(void), void* stack, int stack_size,
                  const char *name IF_PRIO(, int priority));

struct thread_entry*
    create_thread_on_core(unsigned int core, void (*function)(void), 
                          void* stack, int stack_size,
                          const char *name
                          IF_PRIO(, int priority));

#ifdef HAVE_SCHEDULER_BOOSTCTRL
void trigger_cpu_boost(void);
#else
#define trigger_cpu_boost()
#endif

void remove_thread(struct thread_entry *thread);
void switch_thread(bool save_context, struct thread_entry **blocked_list);
void sleep_thread(int ticks);
void block_thread(struct thread_entry **thread, int timeout);
void wakeup_thread(struct thread_entry **thread);
int thread_set_priority(struct thread_entry *thread, int priority);
void init_threads(void);
int thread_stack_usage(const struct thread_entry *thread);
int thread_get_status(const struct thread_entry *thread);
#ifdef RB_PROFILE
void profile_thread(void);
#endif

#endif