Commit 85ec0bcc authored by wdenk's avatar wdenk

* Patch by Arun Dharankar, 24 Mar 2003:

  - add threads / scheduler example code

* Add patches by Robert Schwebel, 31 Mar 2003:
  - add ctrl-c support for kermit download
  - align bdinfo output on ARM

* Add CPU ID, version, and clock speed for INCA-IP
parent 506f0441
......@@ -2,6 +2,15 @@
Changes since U-Boot 0.2.2:
======================================================================
* Patch by Arun Dharankar, 24 Mar 2003:
- add threads / scheduler example code
* Add patches by Robert Schwebel, 31 Mar 2003:
- add ctrl-c support for kermit download
- align bdinfo output on ARM
* Add CPU ID, version, and clock speed for INCA-IP
* Patches by Dave Ellis, 18 Mar 2003 for SXNI855T board:
- fix SRAM and SDRAM memory sizing
- add status LED support
......
......@@ -70,6 +70,10 @@ N: Magnus Damm
E: eramdam@kieray1.p.y.ki.era.ericsson.se
D: 8xxrom
N: Arun Dharankar
E: ADharankar@ATTBI.Com
D: threads / scheduler example code
N: Kri Davsson
E: kd@flaga.is
D: FLAGA DM Support
......
......@@ -84,7 +84,7 @@ LIST_ppc="${LIST_8xx} ${LIST_824x} ${LIST_8260} \
## StrongARM Systems
#########################################################################
LIST_SA="at91rm9200dk dnp1110 lart shannon"
LIST_SA="dnp1110 lart shannon"
#########################################################################
## ARM7 Systems
......@@ -96,7 +96,7 @@ LIST_ARM7="ep7312 impa7"
## ARM9 Systems
#########################################################################
LIST_ARM9="smdk2400 smdk2410 trab VCMA9"
LIST_ARM9="at91rm9200dk smdk2400 smdk2410 trab VCMA9"
#########################################################################
## Xscale Systems
......
......@@ -716,7 +716,8 @@ clean:
\( -name 'core' -o -name '*.bak' -o -name '*~' \
-o -name '*.o' -o -name '*.a' \) -print \
| xargs rm -f
rm -f examples/hello_world examples/timer examples/eepro100_eeprom
rm -f examples/hello_world examples/timer \
examples/eepro100_eeprom examples/sched
rm -f tools/img2srec tools/mkimage tools/envcrc tools/gen_eth_addr
rm -f tools/easylogo/easylogo tools/bmp_logo
rm -f tools/gdb/astest tools/gdb/gdbcont tools/gdb/gdbsend
......
......@@ -1245,7 +1245,7 @@ The following options need to be configured:
Modem Support:
--------------
[so far only for SMDK2400 board]
[so far only for SMDK2400 and TRAB boards]
- Modem support endable:
CONFIG_MODEM_SUPPORT
......@@ -1532,20 +1532,16 @@ has been relocated to RAM and a RAM copy of the environment has been
created; also, when using EEPROM you will have to use getenv_r()
until then to read environment variables.
The environment is now protected by a CRC32 checksum. Before the
monitor is relocated into RAM, as a result of a bad CRC you will be
working with the compiled-in default environment - *silently*!!!
[This is necessary, because the first environment variable we need is
the "baudrate" setting for the console - if we have a bad CRC, we
don't have any device yet where we could complain.]
The environment is protected by a CRC32 checksum. Before the monitor
is relocated into RAM, as a result of a bad CRC you will be working
with the compiled-in default environment - *silently*!!! [This is
necessary, because the first environment variable we need is the
"baudrate" setting for the console - if we have a bad CRC, we don't
have any device yet where we could complain.]
Note: once the monitor has been relocated, then it will complain if
the default environment is used; a new CRC is computed as soon as you
use the "setenv" command to modify / delete / add any environment
variable [even when you try to delete a non-existing variable!].
Note2: you must edit your u-boot.lds file to reflect this
configuration.
use the "saveenv" command to store a valid environment.
Low Level (hardware related) configuration options:
......@@ -1605,16 +1601,16 @@ Low Level (hardware related) configuration options:
- MPC824X: data cache
- PPC4xx: data cache
- CFG_INIT_DATA_OFFSET:
- CFG_GBL_DATA_OFFSET:
Offset of the initial data structure in the memory
area defined by CFG_INIT_RAM_ADDR. Usually
CFG_INIT_DATA_OFFSET is chosen such that the initial
CFG_GBL_DATA_OFFSET is chosen such that the initial
data is located at the end of the available space
(sometimes written as (CFG_INIT_RAM_END -
CFG_INIT_DATA_SIZE), and the initial stack is just
below that area (growing from (CFG_INIT_RAM_ADDR +
CFG_INIT_DATA_OFFSET) downward.
CFG_GBL_DATA_OFFSET) downward.
Note:
On the MPC824X (or other systems that use the data
......@@ -1771,14 +1767,21 @@ to port U-Boot to your hardware platform. To do this, follow these
steps:
1. Add a new configuration option for your board to the toplevel
"Makefile", using the existing entries as examples.
"Makefile" and to the "MAKEALL" script, using the existing
entries as examples. Note that here and at many other places
boards and other names are listed alphabetically sorted. Please
keep this order.
2. Create a new directory to hold your board specific code. Add any
files you need.
files you need. In your board directory, you will need at least
the "Makefile", a "<board>.c", "flash.c" and "u-boot.lds".
3. Create a new configuration file "include/configs/<board>.h" for
your board
3. If you're porting U-Boot to a new CPU, then also create a new
directory to hold your CPU specific code. Add any files you need.
4. Run "make config_name" with your new name.
4. Run "make <board>_config" with your new name.
5. Type "make", and you should get a working "u-boot.srec" file
to be installed on your target system.
6. Debug and solve any problems that might arise.
[Of course, this last step is much harder than it sounds.]
......@@ -2481,6 +2484,17 @@ Hit 'q':
[q, b, e, ?] ## Application terminated, rc = 0x0
Minicom warning:
================
Over time, many people have reported problems when trying to used the
"minicom" terminal emulation program for serial download. I (wd)
consider minicom to be broken, and recommend not to use it. Under
Unix, I recommend to use CKermit for general purpose use (and
especially for kermit binary protocol download ("loadb" command), and
use "cu" for S-Record download ("loads" command).
NetBSD Notes:
=============
......
......@@ -23,7 +23,7 @@
*/
#include <common.h>
#include <AT91RM9200.h>
#include <asm/arch/AT91RM9200.h>
/* ------------------------------------------------------------------------- */
/*
......
......@@ -27,6 +27,8 @@
#include <asm/inca-ip.h>
extern uint incaip_get_cpuclk(void);
static ulong max_sdram_size(void)
{
/* The only supported SDRAM data width is 16bit.
......@@ -127,3 +129,29 @@ long int initdram(int board_type)
return max_size;
}
int checkboard (void)
{
unsigned long chipid = *INCA_IP_WDT_CHIPID;
int part_num;
puts ("Board: INCA-IP ");
part_num = (chipid >> 12) & 0xffff;
switch (part_num) {
case 0xc0:
printf ("Standard Version, ");
break;
case 0xc1:
printf ("Basic Version, ");
break;
default:
printf ("Unknown Part Number 0x%x ", part_num);
break;
}
printf ("Chip V1.%ld, ", (chipid >> 28));
printf("CPU Speed %d MHz\n", incaip_get_cpuclk()/1000000);
return 0;
}
......@@ -68,7 +68,7 @@ memsetup:
sw t1, EBU_ADDSEL0(t0)
#if CPU_CLOCK_RATE==150000000 /* 150 MHz clock for the MIPS core */
li t1, 0xE841417E
li t1, 0xA841417E
sw t1, EBU_BUSCON0(t0) /* value set up by magic flash word */
sw t1, EBU_BUSCON2(t0)
#else /* 100 MHz */
......
......@@ -163,10 +163,10 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]);
}
printf ("\n"
"ip_addr = ");
"ip_addr = ");
print_IPaddr (bd->bi_ip_addr);
printf ("\n"
"baudrate = %d bps\n", bd->bi_baudrate);
"baudrate = %d bps\n", bd->bi_baudrate);
return 0;
}
......@@ -575,6 +575,7 @@ write_record (char *buf)
#define XON_CHAR 17
#define XOFF_CHAR 19
#define START_CHAR 0x01
#define ETX_CHAR 0x03
#define END_CHAR 0x0D
#define SPACE 0x20
#define K_ESCAPE 0x23
......@@ -995,8 +996,18 @@ static int k_recv (void)
#endif
/* get a packet */
/* wait for the starting character */
while (serial_getc () != START_CHAR);
/* wait for the starting character or ^C */
for (;;) {
switch (serial_getc ()) {
case START_CHAR: /* start packet */
break;
case ETX_CHAR: /* ^C waiting for packet */
return (0);
default:
;
}
}
/* get length of packet */
sum = 0;
new_char = serial_getc ();
......
......@@ -1266,6 +1266,7 @@ static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len)
{
unsigned long nandptr;
struct Nand *mychip;
int ret = 0;
if (ofs & (nand->erasesize-1) || len & (nand->erasesize-1)) {
printf ("Offset and size must be sector aligned, erasesize = %d\n",
......@@ -1275,6 +1276,17 @@ static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len)
nandptr = nand->IO_ADDR;
/* Select the NAND device */
NAND_ENABLE_CE(nand); /* set pin low */
/* Check the WP bit */
NanD_Command(nand, NAND_CMD_STATUS);
if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
printf ("nand_write_ecc: Device is write protected!!!\n");
ret = -1;
goto out;
}
/* FIXME: Do nand in the background. Use timers or schedule_task() */
while(len) {
mychip = &nand->chips[shr(ofs, nand->chipshift)];
......@@ -1288,20 +1300,22 @@ static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len)
if (READ_NAND(nandptr) & 1) {
printf("Error erasing at 0x%lx\n", (long)ofs);
/* There was an error */
goto callback;
ret = -1;
goto out;
}
ofs += nand->erasesize;
len -= nand->erasesize;
}
callback:
return 0;
out:
/* De-select the NAND device */
NAND_DISABLE_CE(nand); /* set pin high */
return ret;
}
static inline int nandcheck(unsigned long potential, unsigned long physadr)
{
return 0;
}
......
......@@ -32,7 +32,7 @@
#include <common.h>
#include <command.h>
#include <AT91RM9200.h>
#include <asm/io.h>
/* read co-processor 15, register #1 (control register) */
static unsigned long read_p15_c1(void)
......
......@@ -31,7 +31,7 @@
*/
#include <common.h>
#include <AT91RM9200.h>
#include <asm/io.h>
#include <asm/proc-armv/ptrace.h>
extern void reset_cpu(ulong addr);
......
......@@ -30,7 +30,7 @@
*/
#include <common.h>
#include <AT91RM9200.h>
#include <asm/io.h>
/* ggi thunder */
AT91PS_USART us = (AT91PS_USART) AT91C_BASE_DBGU;
......
#include <common.h>
#include <command.h>
#include <AT91RM9200.h>
#include <asm/io.h>
#include <net.h>
/* ----- Ethernet Buffer definitions ----- */
......
......@@ -28,6 +28,11 @@ include $(TOPDIR)/config.mk
SREC = hello_world.srec
BIN = hello_world.bin
ifeq ($(ARCH),ppc)
SREC += sched.srec
BIN += sched.bin
endif
ifeq ($(CPU),mips)
SREC =
BIN =
......@@ -36,6 +41,7 @@ endif
# The following example is pretty 8xx specific...
ifeq ($(CPU),mpc8xx)
SREC += timer.srec
BIN += timer.bin
endif
# Utility for resetting i82559 EEPROM
......@@ -45,8 +51,11 @@ endif
OBJS = $(SREC:.srec=.o)
LIB = libsyscall.a
LIB = libsyscall.a
LIBAOBJS= syscall.o
ifeq ($(ARCH),ppc)
LIBAOBJS+= $(ARCH)_longjmp.o $(ARCH)_setjmp.o
endif
LIBCOBJS=
LIBOBJS = $(LIBAOBJS) $(LIBCOBJS)
......
/* longjmp for PowerPC.
Copyright (C) 1995, 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <ppc_asm.tmpl>
# define JB_GPR1 0 /* Also known as the stack pointer */
# define JB_GPR2 1
# define JB_LR 2 /* The address we will return to */
# define JB_GPRS 3 /* GPRs 14 through 31 are saved, 18 in total */
# define JB_CR 21 /* Condition code registers. */
# define JB_FPRS 22 /* FPRs 14 through 31 are saved, 18*2 words total */
# define JB_SIZE (58*4)
#define FP(x...) x
#define FP(x...) x
.globl longjmp;
longjmp:
lwz r1,(JB_GPR1*4)(r3)
lwz r2,(JB_GPR2*4)(r3)
lwz r0,(JB_LR*4)(r3)
lwz r14,((JB_GPRS+0)*4)(r3)
FP( lfd 14,((JB_FPRS+0*2)*4)(r3))
lwz r15,((JB_GPRS+1)*4)(r3)
FP( lfd 15,((JB_FPRS+1*2)*4)(r3))
lwz r16,((JB_GPRS+2)*4)(r3)
FP( lfd 16,((JB_FPRS+2*2)*4)(r3))
lwz r17,((JB_GPRS+3)*4)(r3)
FP( lfd 17,((JB_FPRS+3*2)*4)(r3))
lwz r18,((JB_GPRS+4)*4)(r3)
FP( lfd 18,((JB_FPRS+4*2)*4)(r3))
lwz r19,((JB_GPRS+5)*4)(r3)
FP( lfd 19,((JB_FPRS+5*2)*4)(r3))
lwz r20,((JB_GPRS+6)*4)(r3)
FP( lfd 20,((JB_FPRS+6*2)*4)(r3))
mtlr r0
lwz r21,((JB_GPRS+7)*4)(r3)
FP( lfd 21,((JB_FPRS+7*2)*4)(r3))
lwz r22,((JB_GPRS+8)*4)(r3)
FP( lfd 22,((JB_FPRS+8*2)*4)(r3))
lwz r0,(JB_CR*4)(r3)
lwz r23,((JB_GPRS+9)*4)(r3)
FP( lfd 23,((JB_FPRS+9*2)*4)(r3))
lwz r24,((JB_GPRS+10)*4)(r3)
FP( lfd 24,((JB_FPRS+10*2)*4)(r3))
lwz r25,((JB_GPRS+11)*4)(r3)
FP( lfd 25,((JB_FPRS+11*2)*4)(r3))
mtcrf 0xFF,r0
lwz r26,((JB_GPRS+12)*4)(r3)
FP( lfd 26,((JB_FPRS+12*2)*4)(r3))
lwz r27,((JB_GPRS+13)*4)(r3)
FP( lfd 27,((JB_FPRS+13*2)*4)(r3))
lwz r28,((JB_GPRS+14)*4)(r3)
FP( lfd 28,((JB_FPRS+14*2)*4)(r3))
lwz r29,((JB_GPRS+15)*4)(r3)
FP( lfd 29,((JB_FPRS+15*2)*4)(r3))
lwz r30,((JB_GPRS+16)*4)(r3)
FP( lfd 30,((JB_FPRS+16*2)*4)(r3))
lwz r31,((JB_GPRS+17)*4)(r3)
FP( lfd 31,((JB_FPRS+17*2)*4)(r3))
mr r3,r4
blr
/* setjmp for PowerPC.
Copyright (C) 1995, 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <ppc_asm.tmpl>
# define JB_GPR1 0 /* Also known as the stack pointer */
# define JB_GPR2 1
# define JB_LR 2 /* The address we will return to */
# define JB_GPRS 3 /* GPRs 14 through 31 are saved, 18 in total */
# define JB_CR 21 /* Condition code registers. */
# define JB_FPRS 22 /* FPRs 14 through 31 are saved, 18*2 words total */
# define JB_SIZE (58*4)
#define FP(x...) x
.globl setctxsp;
setctxsp:
mr r1, r3
blr
.globl _setjmp;
_setjmp:
stw r1,(JB_GPR1*4)(3)
mflr r0
stw r2,(JB_GPR2*4)(3)
stw r14,((JB_GPRS+0)*4)(3)
FP( stfd 14,((JB_FPRS+0*2)*4)(3))
stw r0,(JB_LR*4)(3)
stw r15,((JB_GPRS+1)*4)(3)
FP( stfd 15,((JB_FPRS+1*2)*4)(3))
mfcr r0
stw r16,((JB_GPRS+2)*4)(3)
FP( stfd 16,((JB_FPRS+2*2)*4)(3))
stw r0,(JB_CR*4)(3)
stw r17,((JB_GPRS+3)*4)(3)
FP( stfd 17,((JB_FPRS+3*2)*4)(3))
stw r18,((JB_GPRS+4)*4)(3)
FP( stfd 18,((JB_FPRS+4*2)*4)(3))
stw r19,((JB_GPRS+5)*4)(3)
FP( stfd 19,((JB_FPRS+5*2)*4)(3))
stw r20,((JB_GPRS+6)*4)(3)
FP( stfd 20,((JB_FPRS+6*2)*4)(3))
stw r21,((JB_GPRS+7)*4)(3)
FP( stfd 21,((JB_FPRS+7*2)*4)(3))
stw r22,((JB_GPRS+8)*4)(3)
FP( stfd 22,((JB_FPRS+8*2)*4)(3))
stw r23,((JB_GPRS+9)*4)(3)
FP( stfd 23,((JB_FPRS+9*2)*4)(3))
stw r24,((JB_GPRS+10)*4)(3)
FP( stfd 24,((JB_FPRS+10*2)*4)(3))
stw r25,((JB_GPRS+11)*4)(3)
FP( stfd 25,((JB_FPRS+11*2)*4)(3))
stw r26,((JB_GPRS+12)*4)(3)
FP( stfd 26,((JB_FPRS+12*2)*4)(3))
stw r27,((JB_GPRS+13)*4)(3)
FP( stfd 27,((JB_FPRS+13*2)*4)(3))
stw r28,((JB_GPRS+14)*4)(3)
FP( stfd 28,((JB_FPRS+14*2)*4)(3))
stw r29,((JB_GPRS+15)*4)(3)
FP( stfd 29,((JB_FPRS+15*2)*4)(3))
stw r30,((JB_GPRS+16)*4)(3)
FP( stfd 30,((JB_FPRS+16*2)*4)(3))
stw r31,((JB_GPRS+17)*4)(3)
FP( stfd 31,((JB_FPRS+17*2)*4)(3))
li 3, 0
blr
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <syscall.h>
#include <setjmp.h>
/*
* Author: Arun Dharankar <ADharankar@ATTBI.Com>
*
* A very simple thread/schedular model:
* - only one master thread, and no parent child relation maintained
* - parent thread cannot be stopped or deleted
* - no permissions or credentials
* - no elaborate safety checks
* - cooperative multi threading
* - Simple round-robin scheduleing with no priorities
* - no metering/statistics collection
*
* Basic idea of implementing this is to allow more than one tests to
* execute "simultaneously".
*
* This may be modified such thread_yield may be called in syscalls, and
* timer interrupts.
*/
#define MAX_THREADS 8
#define CTX_SIZE 512
#define STK_SIZE 8*1024
#define STATE_EMPTY 0
#define STATE_RUNNABLE 1
#define STATE_STOPPED 2
#define STATE_TERMINATED 2
#define MASTER_THREAD 0
#define RC_FAILURE (-1)
#define RC_SUCCESS (0)
struct lthread {
int state;
int retval;
char stack[STK_SIZE];
uchar context[CTX_SIZE];
int (*func) (void *);
void *arg;
};
static volatile struct lthread lthreads[MAX_THREADS];
static volatile int current_tid = MASTER_THREAD;
static uchar dbg = 0;
#define DEBUG(fmt, args...) { \
if(dbg != 0) { \
mon_printf("[%s %d %s]: ", __FILE__, __LINE__, __FUNCTION__); \
mon_printf(fmt, ##args); \
mon_printf("\n"); \
} \
}
static int testthread (void *);
static void sched_init (void);
static int thread_create (int (*func) (void *), void *arg);
static int thread_start (int id);
static void thread_yield (void);
static int thread_delete (int id);
static int thread_join (int *ret);
#if 0 /* not used yet */
static int thread_stop (int id);
#endif /* not used yet */
/* An example of schedular test */
#define NUMTHREADS 7
int sched (bd_t *bd, int ac, char *av[])
{
int i, j;
int tid[NUMTHREADS];
int names[NUMTHREADS];
sched_init ();
for (i = 0; i < NUMTHREADS; i++) {
names[i] = i;
j = thread_create (testthread, (void *) &names[i]);
if (j == RC_FAILURE)
mon_printf ("schedtest: Failed to create thread %d\n",
i);
if (j > 0) {
mon_printf ("schedtest: Created thread with id %d, name %d\n",
j, i);
tid[i] = j;
}
}
mon_printf ("schedtest: Threads created\n");
mon_printf ("sched_test: function=0x%08x\n", testthread);
for (i = 0; i < NUMTHREADS; i++) {
mon_printf ("schedtest: Setting thread %d runnable\n", tid[i]);
thread_start (tid[i]);
thread_yield ();
}
mon_printf ("schedtest: Started %d threads\n", NUMTHREADS);
while (1) {
mon_printf ("schedtest: Waiting for threads to complete\n");
if (mon_tstc () && mon_getc () == 0x3) {
mon_printf ("schedtest: Aborting threads...\n");
for (i = 0; i < NUMTHREADS; i++) {
mon_printf ("schedtest: Deleting thread %d\n",
tid[i]);
thread_delete (tid[i]);
}
return RC_SUCCESS;
}
j = -1;
i = thread_join (&j);
if (i == RC_FAILURE) {
mon_printf ("schedtest: No threads pending, "
"exiting schedular test\n");
return RC_SUCCESS;
}
mon_printf ("schedtest: thread is %d returned %d\n", i,
j);
thread_yield ();
}
return RC_SUCCESS;
}
static int testthread (void *name)
{
int i;
mon_printf ("testthread: Begin executing thread, myname %d, &i=0x%08x\n",
*(int *) name, &i);
mon_printf ("Thread %02d, i=%d\n", *(int *) name);
for (i = 0; i < 0xffff * (*(int *) name + 1); i++) {
if (mon_tstc () && mon_getc () == 0x3) {
mon_printf ("testthread: myname %d terminating.\n",
*(int *) name);
return *(int *) name + 1;
}
if (i % 100 == 0)
thread_yield ();
}
mon_printf ("testthread: returning %d, i=0x%x\n",
*(int *) name + 1, i);
return *(int *) name + 1;
}
static void sched_init (void)
{
int i;
for (i = MASTER_THREAD + 1; i < MAX_THREADS; i++)
lthreads[i].state = STATE_EMPTY;
current_tid = MASTER_THREAD;
lthreads[current_tid].state = STATE_RUNNABLE;
DEBUG ("sched_init: master context = 0x%08x",
lthreads[current_tid].context);
return;
}
static void thread_yield (void)
{
static int i;
DEBUG ("thread_yield: current tid=%d", current_tid);
#define SWITCH(new) \
if(lthreads[new].state == STATE_RUNNABLE) { \
DEBUG("thread_yield: %d match, ctx=0x%08x", \
new, lthreads[current_tid].context); \
if(setjmp(lthreads[current_tid].context) == 0) { \
current_tid = new; \
DEBUG("thread_yield: tid %d returns 0", \
new); \
longjmp(lthreads[new].context, 1); \
} else { \
DEBUG("thread_yield: tid %d returns 1", \
new); \
return; \
} \
}
for (i = current_tid + 1; i < MAX_THREADS; i++) {
SWITCH (i);
}
if (current_tid != 0) {
for (i = 0; i <= current_tid; i++) {
SWITCH (i);
}
}
DEBUG ("thread_yield: returning from thread_yield");
return;
}
static int thread_create (int (*func) (void *), void *arg)