📄 support.c
字号:
//==========================================================================
//
// src/ecos/support.c
//
//==========================================================================
//####BSDCOPYRIGHTBEGIN####
//
// -------------------------------------------
//
// Portions of this software may have been derived from OpenBSD,
// FreeBSD or other sources, and are covered by the appropriate
// copyright disclaimers included herein.
//
// Portions created by Red Hat are
// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
//
// Copyright (C) 2002, 2003 Gary Thomas
// Copyright (C) 2003 Andrew Lunn
// -------------------------------------------
//
//####BSDCOPYRIGHTEND####
//==========================================================================
//==========================================================================
//
// ecos/support.c
//
// eCos wrapper and support functions
//
//==========================================================================
//####BSDCOPYRIGHTBEGIN####
//
// -------------------------------------------
//
// Portions of this software may have been derived from OpenBSD or other sources,
// and are covered by the appropriate copyright disclaimers included herein.
//
// -------------------------------------------
//
//####BSDCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): gthomas, hmt
// Contributors: gthomas, hmt, andrew.lunn@ascom.ch
// Date: 2000-01-10
// Purpose:
// Description:
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
// Support routines, etc., used by network code
#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/sockio.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <net/if.h>
#include <net/netisr.h>
#include <cyg/infra/diag.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/kernel/kapi.h>
#include <cyg/hal/hal_if.h>
#include <cyg/infra/cyg_ass.h>
#ifdef CYGPKG_NET_INET6
#include <netinet/in.h>
#include <netinet6/in6_var.h>
#endif
#if !CYGPKG_NET_DRIVER_FRAMEWORK // Interface
#error At least one network driver framework must be defined!
#else
#include <cyg/io/eth/netdev.h>
// Define table boundaries
CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev );
CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev );
CYG_HAL_TABLE_BEGIN( __NET_INIT_TAB__, _Net_inits );
CYG_HAL_TABLE_END( __NET_INIT_TAB_END__, _Net_inits );
extern struct init_tab_entry __NET_INIT_TAB__[], __NET_INIT_TAB_END__;
// Used for system-wide "ticks per second"
#undef ticks
int hz = 100;
int tick = 10000; // usec per "tick"
volatile struct timeval ktime;
int proc = 0; // unused
int proc0 = 0; // unused
volatile struct timeval mono_time;
// Low-level network debugging & logging
#ifdef CYGPKG_NET_FREEBSD_LOGGING
int cyg_net_log_mask = CYGPKG_NET_FREEBSD_LOGGING;
#endif
#ifdef CYGPKG_NET_INET6
#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL+2048)
#else
#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
#endif
static char netint_stack[STACK_SIZE];
static cyg_thread netint_thread_data;
static cyg_handle_t netint_thread_handle;
cyg_flag_t netint_flags;
#define NETISR_ANY 0xFFFFFFFF // Any possible bit...
extern void cyg_test_exit(void); // TEMP
void
cyg_panic(const char *msg, ...)
{
cyg_uint32 old_ints;
CYG_FAIL( msg );
HAL_DISABLE_INTERRUPTS(old_ints);
diag_printf("PANIC: %s\n", msg);
cyg_test_exit(); // FIXME
}
#define NET_MEMPOOL_SIZE roundup(CYGPKG_NET_MEM_USAGE/4,MSIZE)
#define NET_MBUFS_SIZE roundup(CYGPKG_NET_MEM_USAGE/4,MSIZE)
#define NET_CLUSTERS_SIZE roundup(CYGPKG_NET_MEM_USAGE/2,MCLBYTES)
static unsigned char net_mempool_area[NET_MEMPOOL_SIZE];
static cyg_mempool_var net_mem_pool;
static cyg_handle_t net_mem;
static unsigned char net_mbufs_area[NET_MBUFS_SIZE];
static cyg_mempool_fix net_mbufs_pool;
static cyg_handle_t net_mbufs;
static unsigned char net_clusters_area[NET_CLUSTERS_SIZE];
static cyg_mempool_fix net_clusters_pool;
static cyg_handle_t net_clusters;
static char net_clusters_refcnt[(NET_CLUSTERS_SIZE/MCLBYTES)+1];
int nmbclusters = (NET_CLUSTERS_SIZE/MCLBYTES);
#ifdef CYGDBG_NET_TIMING_STATS
static struct net_stats stats_malloc, stats_free,
stats_memcpy, stats_memset,
stats_mbuf_alloc, stats_mbuf_free, stats_cluster_alloc;
extern struct net_stats stats_in_cksum;
// Display a number of ticks as microseconds
// Note: for improved calculation significance, values are kept in ticks*1000
static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION;
static long ns_per_system_clock;
static void
show_ticks_in_us(cyg_uint32 ticks)
{
long long ns;
ns_per_system_clock = 1000000/rtc_resolution[1];
ns = (ns_per_system_clock * ((long long)ticks * 1000)) /
CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
ns += 5; // for rounding to .01us
diag_printf("%7d.%02d", (int)(ns/1000), (int)((ns%1000)/10));
}
void
show_net_stats(struct net_stats *stats, const char *title)
{
int ave;
ave = stats->total_time / stats->count;
diag_printf("%s:\n", title);
diag_printf(" count: %6d", stats->count);
diag_printf(", min: ");
show_ticks_in_us(stats->min_time);
diag_printf(", max: ");
show_ticks_in_us(stats->max_time);
diag_printf(", total: ");
show_ticks_in_us(stats->total_time);
diag_printf(", ave: ");
show_ticks_in_us(ave);
diag_printf("\n");
// Reset stats
memset(stats, 0, sizeof(*stats));
}
void
show_net_times(void)
{
show_net_stats(&stats_malloc, "Net malloc");
show_net_stats(&stats_free, "Net free");
show_net_stats(&stats_mbuf_alloc, "Mbuf alloc");
show_net_stats(&stats_mbuf_free, "Mbuf free");
show_net_stats(&stats_cluster_alloc, "Cluster alloc");
show_net_stats(&stats_in_cksum, "Checksum");
show_net_stats(&stats_memcpy, "Net memcpy");
show_net_stats(&stats_memset, "Net memset");
}
#endif /* CYGDBG_NET_TIMING_STATS */
void *
cyg_net_malloc(u_long size, int type, int flags)
{
void *res;
START_STATS();
log(LOG_MDEBUG, "Net malloc[%d] = ", size);
if (flags & M_NOWAIT) {
res = cyg_mempool_var_try_alloc(net_mem, size);
} else {
res = cyg_mempool_var_alloc(net_mem, size);
}
if ((flags & M_ZERO) && res) {
memset(res,0,size);
}
FINISH_STATS(stats_malloc);
log(LOG_MDEBUG, "%p\n", res);
return (res);
}
void
cyg_net_free(caddr_t addr, int type)
{
START_STATS();
cyg_mempool_var_free(net_mem, addr);
FINISH_STATS(stats_free);
}
#ifdef CYGDBG_NET_SHOW_MBUFS
struct mbuf *mbinfo[300];
void cyg_net_show_mbufs(void)
{
int i;
diag_printf(" MBUF : TYPE FLGS DATA[LEN] NEXT NEXTPKT\n");
for( i = 0; i < 300; i++ )
{
struct mbuf *m = mbinfo[i];
char *type;
if( m == 0 ) continue;
switch( m->m_hdr.mh_type )
{
case MT_FREE: type="FREE"; break;
case MT_DATA: type="DATA"; break;
case MT_HEADER: type="HEADER"; break;
case MT_SONAME: type="SONAME"; break;
case MT_FTABLE: type="FTABLE"; break;
case MT_CONTROL: type="CONTROL"; break;
case MT_OOBDATA: type="OOBDATA"; break;
default: type="UNKNOWN"; break;
}
diag_printf("%08x: %s %04x %08x[%03d] %08x %08x\n",
m, type,
m->m_hdr.mh_flags,
m->m_hdr.mh_data,
m->m_hdr.mh_len,
m->m_hdr.mh_next,
m->m_hdr.mh_nextpkt);
}
diag_printf(" MBUF : TYPE FLGS DATA[LEN] NEXT NEXTPKT\n");
}
#endif
void *
cyg_net_mbuf_alloc(void)
{
void *res;
START_STATS();
log(LOG_MDEBUG, "Alloc mbuf = ");
res = cyg_mempool_fix_try_alloc(net_mbufs);
FINISH_STATS(stats_mbuf_alloc);
#ifdef CYGDBG_NET_SHOW_MBUFS
{
int i;
for( i = 0; i < (sizeof(mbinfo)/sizeof(mbinfo[0])); i++ )
if( mbinfo[i] == 0 )
{
mbinfo[i] = (struct mbuf *)res;
break;
}
}
#endif
// Check that this nastiness works OK
CYG_ASSERT( dtom(res) == res, "dtom failed, base of mbuf" );
CYG_ASSERT( dtom((char *)res + MSIZE/2) == res, "dtom failed, mid mbuf" );
log(LOG_MDEBUG, "%p\n", res);
return (res);
}
void *
cyg_net_cluster_alloc(void)
{
void *res;
START_STATS();
log(LOG_MDEBUG, "Allocate cluster = ");
res = cyg_mempool_fix_try_alloc(net_clusters);
FINISH_STATS(stats_cluster_alloc);
log(LOG_MDEBUG, "%p\n", res);
return res;
}
static struct vm_zone *vm_zones = (struct vm_zone *)NULL;
vm_zone_t
zinit(char *name, int size, int nentries, int flags, int zalloc)
{
void *res;
vm_zone_t zone = (vm_zone_t)0;
elem *p;
log(LOG_MDEBUG, "zinit '%s', size: %d, num: %d, flags: %d, alloc: %d\n",
name, size, nentries, flags, zalloc);
res = cyg_mempool_var_try_alloc(net_mem, sizeof(struct vm_zone));
if (res) {
zone = (vm_zone_t)res;
res = cyg_mempool_var_try_alloc(net_mem, size*nentries);
}
if (!res) {
log(LOG_MDEBUG, "Can't allocate memory for %s\n", name);
panic("zinit: Out of memory\n");
}
p = (elem *)res;
zone->pool = (elem *)0;
zone->elem_size = size;
zone->name = name;
zone->free = zone->total = nentries;
zone->next = vm_zones;
zone->alloc_tries = zone->alloc_fails = zone->alloc_frees = 0;
vm_zones = zone;
while (nentries-- > 0) {
p->next = zone->pool;
zone->pool = p;
p = (elem *)((char *)p + size);
}
p = zone->pool;
#if 0
while (p) {
log(LOG_MDEBUG, "p: %p, next: %p\n", p, p->next);
p = p->next;
}
#endif
return zone;
}
void *
zalloci(vm_zone_t zone)
{
elem *p;
p = zone->pool;
zone->alloc_tries++;
if (p) {
zone->pool = p->next;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -