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

📄 rtems_glue.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  $Id: rtems_glue.c,v 1.29.2.2 2003/09/15 14:07:57 jennifer Exp $ */#define RTEMS_FAST_MUTEX#ifdef RTEMS_FAST_MUTEX#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1#endif#include <string.h>#include <stdarg.h>#include <stdio.h>#include <errno.h>#include <rtems.h>#include <rtems/libio.h>#include <rtems/error.h>#include <rtems/rtems_bsdnet.h>#include <sys/types.h>#include <sys/param.h>#include <sys/domain.h>#include <sys/mbuf.h>#include <sys/socketvar.h>#include <sys/socket.h>#include <sys/sockio.h>#include <sys/callout.h>#include <sys/proc.h>#include <sys/ioctl.h>#include <net/if.h>#include <net/route.h>#include <netinet/in.h>#include <vm/vm.h>#include <arpa/inet.h>#include <net/netisr.h>#include <net/route.h>/* * Sysctl init all. */void sysctl_register_all(void *arg);/* * Memory allocation */static int nmbuf	= (64 * 1024) / MSIZE;       int nmbclusters	= (128 * 1024) / MCLBYTES;/* * Socket buffering parameters */unsigned long sb_efficiency = 8;/* * Network task synchronization */static rtems_id networkSemaphore;#ifdef RTEMS_FAST_MUTEXSemaphore_Control   *the_networkSemaphore;#endifstatic rtems_id networkDaemonTid;static rtems_unsigned32 networkDaemonPriority;static void networkDaemon (void *task_argument);/* * Network timing */int			rtems_bsdnet_ticks_per_second;int			rtems_bsdnet_microseconds_per_tick;/* * Callout processing */static rtems_interval	ticksWhenCalloutsLastChecked;static struct callout *callfree, calltodo;/* * FreeBSD variables */int nfs_diskless_valid;/* * BOOTP values */struct in_addr rtems_bsdnet_log_host_address = {0};struct in_addr rtems_bsdnet_bootp_server_address = {0};char *rtems_bsdnet_bootp_boot_file_name = 0;char *rtems_bsdnet_bootp_server_name = 0;char *rtems_bsdnet_domain_name = 0;char *rtems_bsdnet_bootp_cmdline = 0;struct in_addr rtems_bsdnet_nameserver[sizeof rtems_bsdnet_config.name_server /			sizeof rtems_bsdnet_config.name_server[0]];int rtems_bsdnet_nameserver_count = 0;struct in_addr rtems_bsdnet_ntpserver[sizeof rtems_bsdnet_config.ntp_server /			sizeof rtems_bsdnet_config.ntp_server[0]];int rtems_bsdnet_ntpserver_count = 0;long rtems_bsdnet_timeoffset = 0;/* * Perform FreeBSD memory allocation. * FIXME: This should be modified to keep memory allocation statistics. */#undef malloc#undef freeextern void *malloc (size_t);extern void free (void *);void *rtems_bsdnet_malloc (unsigned long size, int type, int flags){	void *p;	int try = 0;	for (;;) {		p = malloc (size);		if (p || (flags & M_NOWAIT))			return p;		rtems_bsdnet_semaphore_release ();		if (++try >= 30) {			rtems_bsdnet_malloc_starvation();			try = 0;		}        rtems_task_wake_after (rtems_bsdnet_ticks_per_second);		rtems_bsdnet_semaphore_obtain ();	}}/* * Free FreeBSD memory * FIXME: This should be modified to keep memory allocation statistics. */voidrtems_bsdnet_free (void *addr, int type){	free (addr);}/* * Do the initializations required by the BSD code */static intbsd_init (void){	int i;	char *p;	/*	 * Set up mbuf cluster data strutures	 */	p = malloc ((nmbclusters*MCLBYTES)+MCLBYTES-1);	if (p == NULL) {		printf ("Can't get network cluster memory.\n");		return -1;	}	p = (char *)(((unsigned long)p + (MCLBYTES-1)) & ~(MCLBYTES-1));	mbutl = (struct mbuf *)p;	for (i = 0; i < nmbclusters; i++) {		((union mcluster *)p)->mcl_next = mclfree;		mclfree = (union mcluster *)p;		p += MCLBYTES;		mbstat.m_clfree++;	}	mbstat.m_clusters = nmbclusters;	mclrefcnt = malloc (nmbclusters);	if (mclrefcnt == NULL) {		printf ("Can't get mbuf cluster reference counts memory.\n");		return -1;	}	memset (mclrefcnt, '\0', nmbclusters);	/*	 * Set up mbuf data structures	 */	p = malloc(nmbuf * MSIZE + MSIZE - 1);	p = (char *)(((unsigned int)p + MSIZE - 1) & ~(MSIZE - 1));	if (p == NULL) {		printf ("Can't get network memory.\n");		return -1;	}	for (i = 0; i < nmbuf; i++) {		((struct mbuf *)p)->m_next = mmbfree;		mmbfree = (struct mbuf *)p;		p += MSIZE;	}	mbstat.m_mbufs = nmbuf;	mbstat.m_mtypes[MT_FREE] = nmbuf;	/*	 * Set up domains	 */	{	extern struct domain routedomain;	extern struct domain inetdomain;	routedomain.dom_next = domains;	domains = &routedomain;	inetdomain.dom_next = domains;	domains = &inetdomain;	domaininit (NULL);	}  /*   * Setup the sysctl, normally done by a SYSINIT call.   */  sysctl_register_all(0);    	/*	 * Set up interfaces	 */	ifinit (NULL);	return 0;}/* * Initialize and start network operations */static intrtems_bsdnet_initialize (void){	rtems_status_code sc;	/*	 * Set the priority of all network tasks	 */	if (rtems_bsdnet_config.network_task_priority == 0)		networkDaemonPriority = 100;	else		networkDaemonPriority = rtems_bsdnet_config.network_task_priority;	/*	 * Set the memory allocation limits	 */	if (rtems_bsdnet_config.mbuf_bytecount)		nmbuf = rtems_bsdnet_config.mbuf_bytecount / MSIZE;	if (rtems_bsdnet_config.mbuf_cluster_bytecount)		nmbclusters = rtems_bsdnet_config.mbuf_cluster_bytecount / MCLBYTES;	/*	 * Create the task-synchronization semaphore	 */	sc = rtems_semaphore_create (rtems_build_name('B', 'S', 'D', 'n'),					0,					RTEMS_PRIORITY |						RTEMS_BINARY_SEMAPHORE |						RTEMS_INHERIT_PRIORITY |						RTEMS_NO_PRIORITY_CEILING |						RTEMS_LOCAL,					0,					&networkSemaphore);	if (sc != RTEMS_SUCCESSFUL) {		printf ("Can't create network seamphore: `%s'\n", rtems_status_text (sc));		return -1;	}#ifdef RTEMS_FAST_MUTEX	{	Objects_Locations location;	the_networkSemaphore = _Semaphore_Get( networkSemaphore, &location );	_Thread_Enable_dispatch();	}#endif	/*	 * Compute clock tick conversion factors	 */	rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &rtems_bsdnet_ticks_per_second);	if (rtems_bsdnet_ticks_per_second <= 0)		rtems_bsdnet_ticks_per_second = 1;	rtems_bsdnet_microseconds_per_tick = 1000000 / rtems_bsdnet_ticks_per_second;	/*	 * Ensure that `seconds' is greater than 0	 */    while (rtems_bsdnet_seconds_since_boot() == 0)        rtems_task_wake_after(1);	/*	 * Set up BSD-style sockets	 */	if (bsd_init () < 0)		return -1;	/*	 * Start network daemon	 */	networkDaemonTid = rtems_bsdnet_newproc ("ntwk", 4096, networkDaemon, NULL);	/*	 * Let other network tasks begin	 */	rtems_bsdnet_semaphore_release ();	return 0;}/* * Obtain network mutex */voidrtems_bsdnet_semaphore_obtain (void){#ifdef RTEMS_FAST_MUTEX	ISR_Level level;	_ISR_Disable (level);	_CORE_mutex_Seize (		&the_networkSemaphore->Core_control.mutex,		networkSemaphore,		1,		/* wait */		0,		/* forever */		level		);	if (_Thread_Executing->Wait.return_code)		rtems_panic ("Can't obtain network semaphore\n");#else	rtems_status_code sc;	sc = rtems_semaphore_obtain (networkSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);	if (sc != RTEMS_SUCCESSFUL)		rtems_panic ("Can't obtain network semaphore: `%s'\n", rtems_status_text (sc));#endif}/* * Release network mutex */voidrtems_bsdnet_semaphore_release (void){#ifdef RTEMS_FAST_MUTEX	int i;	_Thread_Disable_dispatch();	i = _CORE_mutex_Surrender (		&the_networkSemaphore->Core_control.mutex,		networkSemaphore,		NULL		);	_Thread_Enable_dispatch();	if (i)		rtems_panic ("Can't release network semaphore\n");#else	rtems_status_code sc;	sc = rtems_semaphore_release (networkSemaphore);	if (sc != RTEMS_SUCCESSFUL)		rtems_panic ("Can't release network semaphore: `%s'\n", rtems_status_text (sc));#endif}/* * Wait for something to happen to a socket buffer */intsbwait(sb)	struct sockbuf *sb;{	rtems_event_set events;	rtems_id tid;	rtems_status_code sc;	/*	 * Soak up any pending events.	 * The sleep/wakeup synchronization in the FreeBSD	 * kernel has no memory.	 */	rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events); 	/*	 * Set this task as the target of the wakeup operation.	 */	rtems_task_ident (RTEMS_SELF, 0, &tid);	sb->sb_sel.si_pid = tid;	/*	 * Show that socket is waiting	 */	sb->sb_flags |= SB_WAIT;	/*	 * Release the network semaphore.	 */	rtems_bsdnet_semaphore_release ();	/*	 * Wait for the wakeup event.	 */	sc = rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, sb->sb_timeo, &events);	/*	 * Reobtain the network semaphore.	 */	rtems_bsdnet_semaphore_obtain ();	/*	 * Return the status of the wait.	 */	switch (sc) {	case RTEMS_SUCCESSFUL:	return 0;	case RTEMS_TIMEOUT:	return EWOULDBLOCK;	default:		return ENXIO;	}}/* * Wake up the task waiting on a socket buffer. */voidsowakeup(so, sb)	register struct socket *so;	register struct sockbuf *sb;{	if (sb->sb_flags & SB_WAIT) {		sb->sb_flags &= ~SB_WAIT;		rtems_event_send (sb->sb_sel.si_pid, SBWAIT_EVENT);	}	if (sb->sb_wakeup) {		(*sb->sb_wakeup) (so, sb->sb_wakeuparg);	}}/* * For now, a socket can be used by only one task at a time. */intsb_lock(sb)	register struct sockbuf *sb;{	rtems_panic ("Socket buffer is already in use.");	return 0;}voidwakeup (void *p){	rtems_panic ("Wakeup called");}/* * Wait for a connection/disconnection event. */intsoconnsleep (struct socket *so){	rtems_event_set events;	rtems_id tid;	rtems_status_code sc;	/*	 * Soak up any pending events.	 * The sleep/wakeup synchronization in the FreeBSD	 * kernel has no memory.	 */	rtems_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events); 	/*	 * Set this task as the target of the wakeup operation.	 */	if (so->so_pgid)		rtems_panic ("Another task is already sleeping on that socket");	rtems_task_ident (RTEMS_SELF, 0, &tid);	so->so_pgid = tid;	/*	 * Wait for the wakeup event.	 */	sc = rtems_bsdnet_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, so->so_rcv.sb_timeo, &events);	/*	 * Relinquish ownership of the socket.	 */	so->so_pgid = 0;	switch (sc) {	case RTEMS_SUCCESSFUL:	return 0;	case RTEMS_TIMEOUT:	return EWOULDBLOCK;	default:		return ENXIO;	}}/* * Wake up a task waiting for a connection/disconnection to complete. */voidsoconnwakeup (struct socket *so){	if (so->so_pgid)		rtems_event_send (so->so_pgid, SOSLEEP_EVENT);}/* * Send an event to the network daemon. * This corresponds to sending a software interrupt in the BSD kernel. */voidrtems_bsdnet_schednetisr (int n){	rtems_event_send (networkDaemonTid, 1 << n);}/* * The network daemon * This provides a context to run BSD software interrupts */static voidnetworkDaemon (void *task_argument){	rtems_status_code sc;	rtems_event_set events;	rtems_interval now;	int ticksPassed;	unsigned32 timeout;	struct callout *c;	for (;;) {		c = calltodo.c_next;		if (c)			timeout = c->c_time;		else			timeout = RTEMS_NO_TIMEOUT;		sc = rtems_bsdnet_event_receive (NETISR_EVENTS,						RTEMS_EVENT_ANY | RTEMS_WAIT,						timeout,						&events);		if ( sc == RTEMS_SUCCESSFUL ) {			if (events & NETISR_IP_EVENT)				ipintr ();			if (events & NETISR_ARP_EVENT)				arpintr ();		}		rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);		ticksPassed = now - ticksWhenCalloutsLastChecked;		if (ticksPassed != 0) {			ticksWhenCalloutsLastChecked = now;						c = calltodo.c_next;			if (c) {				c->c_time -= ticksPassed;				while ((c = calltodo.c_next) != NULL && c->c_time <= 0) {					void *arg;					void (*func) (void *);					func = c->c_func;					arg = c->c_arg;					calltodo.c_next = c->c_next;					c->c_next = callfree;					callfree = c;					(*func)(arg);				}			}		}	}}/* * Structure passed to task-start stub */struct newtask {	void (*entry)(void *);	void *arg;};/* * Task-start stub */static voidtaskEntry (rtems_task_argument arg){	struct newtask t;		/*	 * Pick up task information and free	 * the memory allocated to pass the	 * information to this task.	 */	t = *(struct newtask *)arg;	free ((struct newtask *)arg);	/*	 * Enter the competition for the network semaphore	 */	rtems_bsdnet_semaphore_obtain ();	/*	 * Enter the task	 */	(*t.entry)(t.arg);	rtems_panic ("Network task returned!\n");}/* * Start a network task */rtems_idrtems_bsdnet_newproc (char *name, int stacksize, void(*entry)(void *), void *arg){	struct newtask *t;	char nm[4];	rtems_id tid;	rtems_status_code sc;	strncpy (nm, name, 4);	sc = rtems_task_create (rtems_build_name(nm[0], nm[1], nm[2], nm[3]),		networkDaemonPriority,		stacksize,		RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),		RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,		&tid);	if (sc != RTEMS_SUCCESSFUL)		rtems_panic ("Can't create network daemon `%s': `%s'\n", name, rtems_status_text (sc));	/*	 * Set up task arguments	 */	t = malloc (sizeof *t);	t->entry = entry;

⌨️ 快捷键说明

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