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

📄 dld_taskent.c

📁 Omap5910 上实现双核通信 DSP GateWay
💻 C
字号:
/* * dsp_dld/arm/dld_taskent.c * * DSP Dynamic Loader Daemon: dld_taskent.c * * Copyright (C) 2003-2005 Nokia Corporation * * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com> * * 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 * * 2005/07/07:  DSP Gateway version 3.3 */#include <stdio.h>#include <string.h>#include <unistd.h>#include <malloc.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <sys/mman.h>#include <asm/arch/dsp.h>#include "list.h"#include "dsp_dld.h"#include "dld_malloc.h"#include "dld_server.h"#include "dld_daemon.h"#include "dld_cmd.h"#include "dld_coff.h"#include "dld_memmgr.h"#include "dld_symbol.h"#include "dld_section.h"#define g_taskent_for_each(pos)	taskent_for_each(pos, &g_tasklist)static LIST_HEAD(g_tasklist);static struct taskent *taskent_new(char *dnm, char *tnm, unsigned int pri,				   char *ofn, char *cnm);static struct taskent *taskent_find_by_coffname(char *fn);struct taskent *taskent_next(struct taskent *te){	if (te == NULL)		return list_entry(g_tasklist.next, struct taskent, list_head);	if (te->list_head.next == &g_tasklist)		return NULL;	return list_entry(te->list_head.next, struct taskent, list_head);}static struct taskent *taskent_new(char *dnm, char *tnm, unsigned int pri,				   char *ofn, char *cnm){	struct taskent *te = dld_malloc(sizeof(struct taskent), "taskent");	struct taskent *te_share;	if (te == NULL)		return NULL;	INIT_LIST_HEAD(&te->list_head);	te->devname = dld_strdup(dnm, "taskent->devname");	if (te->devname == NULL)		goto fail;	te->taskname = dld_strdup(tnm, "taskent->taskname");	if (te->taskname == NULL)		goto fail;	te->pri = pri;	te->lkcmd = (strlen(cnm) > 0) ? lkcmd_new(cnm) : NULL;	te->minor = -1;	te->request = TREQ_NONE;	if ((te_share = taskent_find_by_coffname(ofn)) != NULL)		te->cobj = te_share->cobj;	else		te->cobj = coff_new(ofn);	te->cobj->taskcount++;	return te;fail:	if (te->devname)		dld_free(te, "taskent->devname");	if (te->taskname)		dld_free(te, "taskent->taskname");	if (te)		dld_free(te, "taskent");	return NULL;}void taskent_freelist(void){	struct taskent *te, *tmp;	taskent_for_each_safe(te, tmp, &g_tasklist) {		list_del(&te->list_head);		if (te->devname)			dld_free(te->devname, "taskent->devname");		if (te->taskname)			dld_free(te->taskname, "taskent->taskname");		if (te->lkcmd)			lkcmd_free(te->lkcmd);		if (--te->cobj->taskcount == 0)			coff_free(te->cobj);		dld_free(te, "taskent");	}}static int parse_config_line(struct dld_conf *conf, char *s, int line_num){	if (s[0] == '$') {		/* var */		char key[32] = { '\0' };		char val[128] = { '\0' };		sscanf(s, "%s %s", key, val);		if (!strcmp(key, "$kernel")) {			if (!conf->knlfn)				conf->knlfn = dld_strdup(val, "dld_conf->knlfn");		} else if (!strcmp(key, "$cmd")) {			if (!conf->cmdfn)				conf->cmdfn = dld_strdup(val, "dld_conf->cmdfn");		} else {			prmsg("error in %s: unknown variable %s at line %d\n",			      conf->cfgfn, key, line_num);			return -1;		}	} else {		/* task entry */		char dnm[128] = { '\0' };		char tnm[128] = { '\0' };		unsigned int pri = 0;		char ofn[128] = { '\0' };		char cnm[128] = { '\0' };		struct taskent *te;		switch (sscanf(s, "%s %s %d %s %s", dnm, tnm, &pri, ofn, cnm)) {			case 4:			case 5:				te = taskent_new(dnm, tnm, pri, ofn, cnm);				list_add_tail(&te->list_head, &g_tasklist);				break;			default:				prmsg("error in %s at line %d.\n",				      conf->cfgfn, line_num);				return -1;		}	}	return 0;}int taskent_readconfig(struct dld_conf *conf){	int fd;	struct stat stat;	size_t size;	char *src, *endp;	char *p, *bl;	int comment;	int line_num;	if ((fd = open(conf->cfgfn, O_RDONLY)) < 0) {		prmsg("Can't open %s\n", conf->cfgfn);		return -1;	}	/* acquiring file size */	if (fstat(fd, &stat) < 0) {		prmsg("%s: fstat() failed\n", conf->cfgfn);		return -1;	}	size = stat.st_size;	/* mmap */	if ((src = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) < 0) {		prmsg("%s: mmap() failed\n", conf->cfgfn);		return -1;	}	endp = src + size;	comment = 0;	line_num = 1;	bl = src;	for (p = src; ; p++) {		int eol;		eol = (*p == '#') || (*p == '\n') || (p == endp);		if (eol && (p > bl) && (!comment)) {			char lbuf[256];			strncpy(lbuf, bl, p - bl);			lbuf[p - bl] = '\0';			if (parse_config_line(conf, lbuf, line_num) < 0)				return -1;		}		if (p == endp)			break;		if (*p == '#')			comment = 1;		if (*p == '\n') {			comment = 0;			bl = p + 1;			line_num++;		}	}	munmap(src, size);	close(fd);	return 0;}int taskent_mkdev(int fd){#ifdef DSP_EMULATION	struct taskent *te;	static int minor = 0;	g_taskent_for_each(te) {		te->minor = minor++;	}	return 0;#else	struct taskent *te;	int minor;	char path1[20];	char path2[20 + OMAP_DSP_TNM_LEN];	struct stat file_stat;	/*	 * Firstly we make all task devices.	 */	g_taskent_for_each(te) {		prmsg("mkdev %s\n", te->devname);		minor = ioctl(fd, OMAP_DSP_TWCH_IOCTL_MKDEV, te->devname);		if (minor < 0) {			prmsg("MKDEV failed\n");			return -1;		}		te->minor = minor;	}	/*	 * Then wait for udevd to create the nodes.	 */	g_taskent_for_each(te) {		int retry = 5;		sprintf(path1, "/dev/dsptask%d", te->minor);		sprintf(path2, TASKDEV_DIR "/%s", te->devname);#if 0 // 3.1		if (stat(path1, &file_stat) < 0)			continue;	/* probably devfs system */#elseretry:		if (stat(path1, &file_stat) < 0) {			/* wait for udevd creates the node */			if (--retry) {				sleep(1);				goto retry;			}			prmsg("stat failed for %s\n", path1);			return -1;		}#endif		if (stat(path2, &file_stat) >= 0)			unlink(path2);	/* garbage */		if (symlink(path1, path2) < 0) {			prmsg("symlink(%s,%s) failed\n", path1, path2);			return -1;		}	}	return 0;#endif}int taskent_rmdev(int fd){#ifdef DSP_EMULATION	return 0;#else	int ret = 0;	struct taskent *te;#if 0 // 3.1	char path1[20];#endif	char path2[20 + OMAP_DSP_TNM_LEN];#if 0 // 3.1	struct stat file_stat;#endif	g_taskent_for_each(te) {#if 0 // 3.1		sprintf(path1, "/dev/dsptask%d", te->minor);#endif		sprintf(path2, TASKDEV_DIR "/%s", te->devname);#if 0 // 3.1		if (stat(path1, &file_stat) < 0)			continue;	/* probably devfs system */#endif		if (unlink(path2) < 0) {			prmsg("unlink(%s) failed\n", path2);			ret = -1;		}		prmsg("rmdev %s\n", te->devname);		if (ioctl(fd, OMAP_DSP_TWCH_IOCTL_RMDEV, te->devname) < 0) {			prmsg("rmdev failed\n");			ret = -1;		}	}	return ret;#endif}#ifndef DSP_EMULATIONint taskent_process_request_all(void){	struct taskent *te;	int ret;	g_taskent_for_each(te) {		switch (te->request) {			case TREQ_ADD:				if ((ret = twch_tadd(te)) < 0)					return ret;				break;			case TREQ_DEL:				if ((ret =twch_tdel(te)) < 0)					return ret;				break;			default:				break;		}	}	return 0;}#endif /* !DSP_EMULATION */struct taskent *taskent_find_by_minor(u8 minor){	struct taskent *te;	g_taskent_for_each(te) {		if (te->minor == minor)			return te;	}	/* not found */	return NULL;}static struct taskent *taskent_find_by_coffname(char *fn){	struct taskent *te;	g_taskent_for_each(te) {		if (!strcmp(te->cobj->fn, fn))			return te;	}	/* not found */	return NULL;}int taskent_register_lkcmd(struct taskent *te, struct lkcmd *lkcmd){	struct memmgr *mem, *tmp;	if (!list_empty(&te->lkcmd->memlist)) {		prmsg("te->lkcmd->memlist is not empty at %s line %d\n",		      __FILE__, __LINE__);		return -1;	}	memmgr_for_each_safe(mem, tmp, &lkcmd->memlist) {		if (!memmgr_validate(mem))			return -1;		mem->lkcmd = te->lkcmd;		list_del(&mem->list_head);		list_add_tail(&mem->list_head, &te->lkcmd->memlist);	}#ifndef DSP_EMULATION	memmgr_exmap(&te->lkcmd->memlist);#endif	list_splice(&lkcmd->dirlist, &te->lkcmd->dirlist);	INIT_LIST_HEAD(&lkcmd->dirlist);	list_splice(&lkcmd->exprlist, &te->lkcmd->exprlist);	INIT_LIST_HEAD(&lkcmd->exprlist);	list_splice(&lkcmd->loptlist, &te->lkcmd->loptlist);	INIT_LIST_HEAD(&lkcmd->loptlist);	return 0;}struct memmgr *taskent_mem_range_user(u32 base, u32 size){	struct taskent *te;	g_taskent_for_each(te) {		struct list_head *memlist;		struct memmgr *mem;		if (!te->lkcmd)			continue;		memlist = &te->lkcmd->memlist;		if (list_empty(memlist))			continue;		mem = memmgr_range_user(memlist, base, size);		if (mem)			return mem;	}	return NULL;}void taskent_mem_sendstat(int fd){	char buf[256];	struct server_event *e = (struct server_event *)buf;	size_t strsz = 256 - SERVER_EVENT_HDRSZ;	int cnt;	struct taskent *te;	g_taskent_for_each(te) {		struct list_head *memlist;		if (!te->lkcmd)			continue;		memlist = &te->lkcmd->memlist;		if (list_empty(memlist))			continue;		cnt = snprintf(e->data.s, strsz, "\n%s:\n", te->taskname);		e->event = DLD_EVENT_STRING;		e->len = SERVER_EVENT_HDRSZ + cnt;		write(fd, e, e->len);		memmgr_sendstat(memlist, fd);	}}void taskent_sym_sendstat(int fd){	char buf[256];	struct server_event *e = (struct server_event *)buf;	size_t strsz = 256 - SERVER_EVENT_HDRSZ;	int cnt;	struct taskent *te;	g_taskent_for_each(te) {		struct list_head *symlist = &te->cobj->symlist;		if (list_empty(symlist))			continue;		cnt = snprintf(e->data.s, strsz, "\n%s:\n", te->taskname);		e->event = DLD_EVENT_STRING;		e->len = SERVER_EVENT_HDRSZ + cnt;		write(fd, e, e->len);		symbol_sendstat(symlist, fd);	}}void taskent_scn_sendstat(int fd){	char buf[256];	struct server_event *e = (struct server_event *)buf;	size_t strsz = 256 - SERVER_EVENT_HDRSZ;	int cnt;	struct taskent *te;	g_taskent_for_each(te) {		struct list_head *scnlist = &te->cobj->scnlist;		if (list_empty(scnlist))			continue;		cnt = snprintf(e->data.s, strsz, "\n%s:\n", te->taskname);		e->event = DLD_EVENT_STRING;		e->len = SERVER_EVENT_HDRSZ + cnt;		write(fd, e, e->len);		section_sendstat(scnlist, fd);	}}void taskent_sendstat(int fd){	char buf[256];	struct server_event *e = (struct server_event *)buf;	size_t strsz = 256 - SERVER_EVENT_HDRSZ;	int cnt;	struct taskent *te;	e->event = DLD_EVENT_STRING;	g_taskent_for_each(te) {		cnt = snprintf(e->data.s, strsz, "device %s (minor=%d):\n",			       te->devname, te->minor);		e->len = SERVER_EVENT_HDRSZ + cnt;		write(fd, e, e->len);		cnt = snprintf(e->data.s, strsz, "  priority    = %d\n", te->pri);		e->len = SERVER_EVENT_HDRSZ + cnt;		write(fd, e, e->len);		cnt = snprintf(e->data.s, strsz, "  task symbol = %s\n",			       te->taskname);		e->len = SERVER_EVENT_HDRSZ + cnt;		write(fd, e, e->len);		cnt = snprintf(e->data.s, strsz,			       "  module      = %s (usecount = %d)\n",			       te->cobj->fn, te->cobj->usecount);		e->len = SERVER_EVENT_HDRSZ + cnt;		write(fd, e, e->len);		cnt = snprintf(e->data.s, strsz, "  cmd file    = %s\n\n",			       te->lkcmd ? te->lkcmd->fn : "");		e->len = SERVER_EVENT_HDRSZ + cnt;		write(fd, e, e->len);	}}/* * debug stuff */void taskent_printstat(void){	struct taskent *te;	prmsg("taskent list status...\n");	g_taskent_for_each(te) {		prmsg("device %s (minor=%d):\n"		      "  priority    = %d\n"		      "  task symbol = %s\n"		      "  module      = %s (usecount = %d)\n"		      "  cmd file    = %s\n\n",		      te->devname, te->minor, te->pri, te->taskname,		      te->cobj->fn, te->cobj->usecount,		      te->lkcmd ? te->lkcmd->fn : "");	}}

⌨️ 快捷键说明

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