⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sched.c

📁 u-boot-1.1.6 源码包
💻 C
字号:
/* * 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 <exports.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)typedef	vu_char *jmp_ctx;unsigned long setctxsp (vu_char *sp);int ppc_setjmp(jmp_ctx env);void ppc_longjmp(jmp_ctx env, int val);#define setjmp	ppc_setjmp#define longjmp	ppc_longjmpstruct 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 PDEBUG(fmt, args...)	 {					\	if(dbg != 0) {							\		printf("[%s %d %s]: ",__FILE__,__LINE__,__FUNCTION__);\		printf(fmt, ##args);				\		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 7int sched (int ac, char *av[]){	int i, j;	int tid[NUMTHREADS];	int names[NUMTHREADS];	app_startup(av);	sched_init ();	for (i = 0; i < NUMTHREADS; i++) {		names[i] = i;		j = thread_create (testthread, (void *) &names[i]);		if (j == RC_FAILURE)			printf ("schedtest: Failed to create thread %d\n", i);		if (j > 0) {			printf ("schedtest: Created thread with id %d, name %d\n",						j, i);			tid[i] = j;		}	}	printf ("schedtest: Threads created\n");	printf ("sched_test: function=0x%08x\n", (unsigned)testthread);	for (i = 0; i < NUMTHREADS; i++) {		printf ("schedtest: Setting thread %d runnable\n", tid[i]);		thread_start (tid[i]);		thread_yield ();	}	printf ("schedtest: Started %d threads\n", NUMTHREADS);	while (1) {		printf ("schedtest: Waiting for threads to complete\n");		if (tstc () && getc () == 0x3) {			printf ("schedtest: Aborting threads...\n");			for (i = 0; i < NUMTHREADS; i++) {				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) {			printf ("schedtest: No threads pending, "						"exiting schedular test\n");			return RC_SUCCESS;		}		printf ("schedtest: thread is %d returned %d\n", i, j);		thread_yield ();	}	return RC_SUCCESS;}static int testthread (void *name){	int i;	printf ("testthread: Begin executing thread, myname %d, &i=0x%08x\n",		*(int *) name, (unsigned)&i);	printf ("Thread %02d, i=%d\n", *(int *) name, i);	for (i = 0; i < 0xffff * (*(int *) name + 1); i++) {		if (tstc () && getc () == 0x3) {			printf ("testthread: myname %d terminating.\n",						*(int *) name);			return *(int *) name + 1;		}		if (i % 100 == 0)			thread_yield ();	}	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;	PDEBUG ("sched_init: master context = 0x%08x",		(unsigned)lthreads[current_tid].context);	return;}static void thread_yield (void){	static int i;	PDEBUG ("thread_yield: current tid=%d", current_tid);#define SWITCH(new) 							\	if(lthreads[new].state == STATE_RUNNABLE) {			\		PDEBUG("thread_yield: %d match, ctx=0x%08x",		\			new,						\			(unsigned)lthreads[current_tid].context);	\		if(setjmp(lthreads[current_tid].context) == 0) {	\			current_tid = new;				\			PDEBUG("thread_yield: tid %d returns 0",	\				new); 					\			longjmp(lthreads[new].context, 1);		\		} else {						\			PDEBUG("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);		}	}	PDEBUG ("thread_yield: returning from thread_yield");	return;}static int thread_create (int (*func) (void *), void *arg){	int i;	for (i = MASTER_THREAD + 1; i < MAX_THREADS; i++) {		if (lthreads[i].state == STATE_EMPTY) {			lthreads[i].state = STATE_STOPPED;			lthreads[i].func = func;			lthreads[i].arg = arg;			PDEBUG ("thread_create: returns new tid %d", i);			return i;		}	}	PDEBUG ("thread_create: returns failure");	return RC_FAILURE;}static int thread_delete (int id){	if (id <= MASTER_THREAD || id > MAX_THREADS)		return RC_FAILURE;	if (current_tid == id)		return RC_FAILURE;	lthreads[id].state = STATE_EMPTY;	return RC_SUCCESS;}static void thread_launcher (void){	PDEBUG ("thread_launcher: invoking func=0x%08x",		   (unsigned)lthreads[current_tid].func);	lthreads[current_tid].retval =			lthreads[current_tid].func (lthreads[current_tid].arg);	PDEBUG ("thread_launcher: tid %d terminated", current_tid);	lthreads[current_tid].state = STATE_TERMINATED;	thread_yield ();	printf ("thread_launcher: should NEVER get here!\n");	return;}static int thread_start (int id){	PDEBUG ("thread_start: id=%d", id);	if (id <= MASTER_THREAD || id > MAX_THREADS) {		return RC_FAILURE;	}	if (lthreads[id].state != STATE_STOPPED)		return RC_FAILURE;	if (setjmp (lthreads[current_tid].context) == 0) {		lthreads[id].state = STATE_RUNNABLE;		current_tid = id;		PDEBUG ("thread_start: to be stack=0%08x",			(unsigned)lthreads[id].stack);		setctxsp ((vu_char *)&lthreads[id].stack[STK_SIZE]);		thread_launcher ();	}	PDEBUG ("thread_start: Thread id=%d started, parent returns", id);	return RC_SUCCESS;}#if 0	/* not used so far */static int thread_stop (int id){	if (id <= MASTER_THREAD || id >= MAX_THREADS)		return RC_FAILURE;	if (current_tid == id)		return RC_FAILURE;	lthreads[id].state = STATE_STOPPED;	return RC_SUCCESS;}#endif	/* not used so far */static int thread_join (int *ret){	int i, j = 0;	PDEBUG ("thread_join: *ret = %d", *ret);	if (!(*ret == -1 || *ret > MASTER_THREAD || *ret < MAX_THREADS)) {		PDEBUG ("thread_join: invalid tid %d", *ret);		return RC_FAILURE;	}	if (*ret == -1) {		PDEBUG ("Checking for tid = -1");		while (1) {			/* PDEBUG("thread_join: start while-loopn"); */			j = 0;			for (i = MASTER_THREAD + 1; i < MAX_THREADS; i++) {				if (lthreads[i].state == STATE_TERMINATED) {					*ret = lthreads[i].retval;					lthreads[i].state = STATE_EMPTY;					/* PDEBUG("thread_join: returning retval %d of tid %d",					   ret, i); */					return RC_SUCCESS;				}				if (lthreads[i].state != STATE_EMPTY) {					PDEBUG ("thread_join: %d used slots tid %d state=%d",						   j, i, lthreads[i].state);					j++;				}			}			if (j == 0) {				PDEBUG ("thread_join: all slots empty!");				return RC_FAILURE;			}			/*  PDEBUG("thread_join: yielding"); */			thread_yield ();			/*  PDEBUG("thread_join: back from yield"); */		}	}	if (lthreads[*ret].state == STATE_TERMINATED) {		i = *ret;		*ret = lthreads[*ret].retval;		lthreads[*ret].state = STATE_EMPTY;		PDEBUG ("thread_join: returing %d for tid %d", *ret, i);		return RC_SUCCESS;	}	PDEBUG ("thread_join: thread %d is not terminated!", *ret);	return RC_FAILURE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -