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

📄 task.c

📁 P2P模拟器
💻 C
字号:
/* Copyright (c) 2005 Russ Cox, MIT; see COPYRIGHT */#include "taskimpl.h"#include <fcntl.h>typedef struct Tasklist Tasklist;struct Tasklist{	Task *head;	Task *tail;};int	taskdebuglevel;int	taskcount;int	tasknswitch;int	taskexitval;Task	*taskrunning;Context	taskschedcontext;Tasklist	taskrunqueue;static char *argv0;static	void		addtask(Tasklist*, Task*);static	void		deltask(Tasklist*, Task*);static	void		contextswitch(Context *from, Context *to);static voidtaskdebug(char *fmt, ...){	va_list arg;	char buf[128];	Task *t;	char *p;	static int fd = -1;return;	va_start(arg, fmt);	vfprint(1, fmt, arg);	va_end(arg);return;	if(fd < 0){		p = strrchr(argv0, '/');		if(p)			p++;		else			p = argv0;		snprint(buf, sizeof buf, "/tmp/%s.tlog", p);		if((fd = open(buf, O_CREAT|O_WRONLY, 0666)) < 0)			fd = open("/dev/null", O_WRONLY);	}	va_start(arg, fmt);	vsnprint(buf, sizeof buf, fmt, arg);	va_end(arg);	t = taskrunning;	if(t)		fprint(fd, "%d.%d: %s\n", getpid(), t->id, buf);	else		fprint(fd, "%d._: %s\n", getpid(), buf);}static voidtaskstart(uint y, uint x){	Task *t;	ulong z;	z = x<<16;	/* hide undefined 32-bit shift from 32-bit compilers */	z <<= 16;	z |= y;	t = (Task*)z;//print("taskstart %p\n", v);	t->startfn(t->startarg);//print("taskexits %p\n", v);	taskexit(0);//print("not reacehd\n");}static int taskidgen;static Task*taskalloc(void (*fn)(void*), void *arg, uint stack){	Task *t;	sigset_t zero;	uint x, y;	ulong z;	/* allocate the task and stack together */	t = malloc(sizeof *t+stack);	if(t == nil){		fprint(2, "taskalloc malloc: %r\n");		abort();	}	memset(t, 0, sizeof *t);	t->stk = (uchar*)(t+1);	t->stksize = stack;	t->id = ++taskidgen;	t->startfn = fn;	t->startarg = arg;	/* do a reasonable initialization */	memset(&t->context.uc, 0, sizeof t->context.uc);	sigemptyset(&zero);	sigprocmask(SIG_BLOCK, &zero, &t->context.uc.uc_sigmask);	/* must initialize with current context */	if(getcontext(&t->context.uc) < 0){		fprint(2, "getcontext: %r\n");		abort();	}	/* call makecontext to do the real work. */	/* leave a few words open on both ends */	t->context.uc.uc_stack.ss_sp = t->stk+8;	t->context.uc.uc_stack.ss_size = t->stksize-64;#ifdef __sun__		/* sigh */	/* can avoid this with __MAKECONTEXT_V2_SOURCE but only on SunOS 5.9 */	t->context.uc.uc_stack.ss_sp = 		(char*)t->context.uc.uc_stack.ss_sp		+t->context.uc.uc_stack.ss_size;#endif	/*	 * All this magic is because you have to pass makecontext a	 * function that takes some number of word-sized variables,	 * and on 64-bit machines pointers are bigger than words.	 */	z = (ulong)t;	y = z;	z >>= 16;	/* hide undefined 32-bit shift from 32-bit compilers */	x = z>>16;	makecontext(&t->context.uc, (void(*)())taskstart, 2, y, x);	return t;}inttaskcreate(void (*fn)(void*), void *arg, uint stack){	int id;	Task *t;	t = taskalloc(fn, arg, stack);	taskcount++;	id = t->id;	taskready(t);	return id;}voidtaskswitch(void){	needstack(0);	contextswitch(&taskrunning->context, &taskschedcontext);}voidtaskready(Task *t){	addtask(&taskrunqueue, t);}inttaskyield(void){	int n;		n = tasknswitch;	taskready(taskrunning);	taskswitch();	return tasknswitch - n;}intanyready(void){	return taskrunqueue.head != nil;}voidtaskexitall(int val){	exit(val);}voidtaskexit(int val){	taskexitval = val;	taskrunning->exiting = 1;	taskswitch();}static voidcontextswitch(Context *from, Context *to){	if(swapcontext(&from->uc, &to->uc) < 0){		fprint(2, "swapcontext failed: %r\n");		assert(0);	}}static voidtaskscheduler(void){	Task *t;	taskdebug("scheduler enter");	for(;;){		t = taskrunqueue.head;		if(t == nil){			if(taskcount == 0)				exit(taskexitval);			fprint(2, "no runnable tasks! %d tasks stalled\n", taskcount);			exit(1);		}		deltask(&taskrunqueue, t);		taskrunning = t;		tasknswitch++;		taskdebug("run %d (%s)", t->id, t->name);		contextswitch(&taskschedcontext, &t->context);//print("back in scheduler\n");		taskrunning = nil;		if(t->exiting){			taskcount--;			free(t);		}	}}void**taskdata(void){	return &taskrunning->udata;}/* * debugging */voidtasksetname(char *fmt, ...){	va_list arg;	Task *t;	t = taskrunning;	va_start(arg, fmt);	vsnprint(t->name, sizeof t->name, fmt, arg);	va_end(arg);}char*taskgetname(void){	return taskrunning->name;}voidtasksetstate(char *fmt, ...){	va_list arg;	Task *t;	t = taskrunning;	va_start(arg, fmt);	vsnprint(t->state, sizeof t->name, fmt, arg);	va_end(arg);}voidneedstack(int n){	Task *t;	t = taskrunning;	if((char*)&t <= (char*)t->stk	|| (char*)&t - (char*)t->stk < 256+n){		fprint(2, "task stack overflow: &t=%p tstk=%p n=%d\n", &t, t->stk, 256+n);		abort();	}}/* * startup */static int taskargc;static char **taskargv;int mainstacksize;static voidtaskmainstart(void *v){	taskmain(taskargc, taskargv);}intmain(int argc, char **argv){	argv0 = argv[0];	taskargc = argc;	taskargv = argv;	if(mainstacksize == 0)		mainstacksize = 256*1024;	taskcreate(taskmainstart, nil, mainstacksize);	taskscheduler();	fprint(2, "taskscheduler returned in main!\n");	abort();	return 0;}/* * hooray for linked lists */static voidaddtask(Tasklist *l, Task *t){	if(l->tail){		l->tail->next = t;		t->prev = l->tail;	}else{		l->head = t;		t->prev = nil;	}	l->tail = t;	t->next = nil;}static voiddeltask(Tasklist *l, Task *t){	if(t->prev)		t->prev->next = t->next;	else		l->head = t->next;	if(t->next)		t->next->prev = t->prev;	else		l->tail = t->prev;}unsigned inttaskid(void){	return taskrunning->id;}

⌨️ 快捷键说明

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