📄 support.c
字号:
//==========================================================================//// 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// 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/kernel.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/route.h>#include <net/netisr.h>#include <netinet/in.h>#include <netinet/in_var.h>#include <arpa/inet.h>#include <machine/cpu.h>#include <pkgconf/net.h>#include <cyg/infra/diag.h>#include <cyg/hal/hal_intr.h>#include <cyg/kernel/kapi.h>#include <cyg/infra/cyg_ass.h>#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 boundariesCYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev );CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev );// Used for system-wide "ticks per second"int hz = 100;int tick = 10000; // usec per "tick"volatile struct timeval mono_time;volatile struct timeval ktime;// Low-level network debuggingint net_debug = 0;#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICALstatic 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); // TEMPvoidcyg_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}// Round a number 'n' up to a multiple of 'm'#define round(n,m) ((((n)+((m)-1))/(m))*(m))#define NET_MEMPOOL_SIZE round(CYGPKG_NET_MEM_USAGE/4,MSIZE)#define NET_MBUFS_SIZE round(CYGPKG_NET_MEM_USAGE/4,MSIZE)#define NET_CLUSTERS_SIZE round(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];#ifdef CYGDBG_NET_TIMING_STATSstatic 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*1000static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION;static long ns_per_system_clock;static voidshow_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));}voidshow_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));}voidshow_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(); if (flags & M_NOWAIT) { res = cyg_mempool_var_try_alloc(net_mem, size); } else { res = cyg_mempool_var_alloc(net_mem, size); } FINISH_STATS(stats_malloc); return (res);}void cyg_net_free(caddr_t addr, int type){ START_STATS(); cyg_mempool_var_free(net_mem, addr); FINISH_STATS(stats_free);}void *cyg_net_mbuf_alloc(int type, int flags){ void *res; START_STATS(); mbstat.m_mbufs++; if (flags & M_NOWAIT) { res = cyg_mempool_fix_try_alloc(net_mbufs); } else { res = cyg_mempool_fix_alloc(net_mbufs); } FINISH_STATS(stats_mbuf_alloc); // 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" ); return (res);}void cyg_net_mbuf_free(caddr_t addr, int type){ START_STATS(); mbstat.m_mbufs--; cyg_mempool_fix_free(net_mbufs, addr); FINISH_STATS(stats_mbuf_free);}void *cyg_net_cluster_alloc(void){ void *res; START_STATS(); res = cyg_mempool_fix_try_alloc(net_clusters); FINISH_STATS(stats_cluster_alloc); return res;}static voidcyg_kmem_init(void){ unsigned char *p;#ifdef CYGPKG_NET_DEBUG diag_printf("Network stack using %d bytes for misc space\n", NET_MEMPOOL_SIZE); diag_printf(" %d bytes for mbufs\n", NET_MBUFS_SIZE); diag_printf(" %d bytes for mbuf clusters\n", NET_CLUSTERS_SIZE);#endif cyg_mempool_var_create(&net_mempool_area, NET_MEMPOOL_SIZE, &net_mem, &net_mem_pool); // Align the mbufs on MSIZE boudaries so that dtom() can work. p = (unsigned char *)(((long)(&net_mbufs_area) + MSIZE - 1) & ~(MSIZE-1)); cyg_mempool_fix_create(p, ((&(net_mbufs_area[NET_MBUFS_SIZE])) - p) & ~(MSIZE-1), MSIZE, &net_mbufs, &net_mbufs_pool); cyg_mempool_fix_create(&net_clusters_area, NET_CLUSTERS_SIZE, MCLBYTES, &net_clusters, &net_clusters_pool); mbutl = (struct mbuf *)&net_clusters_area; mclrefcnt = net_clusters_refcnt;}void cyg_kmem_print_stats( void ){ cyg_mempool_info info; diag_printf( "Network stack mbuf stats:\n" ); diag_printf( " mbufs %d, clusters %d, free clusters %d\n", mbstat.m_mbufs, /* mbufs obtained from page pool */ mbstat.m_clusters, /* clusters obtained from page pool */ /* mbstat.m_spare, */ /* spare field */ mbstat.m_clfree /* free clusters */ ); diag_printf( " Failed to get %d times\n" " Waited to get %d times\n" " Drained queues to get %d times\n", mbstat.m_drops, /* times failed to find space */ mbstat.m_wait, /* times waited for space */ mbstat.m_drain /* times drained protocols for space */ /* mbstat.m_mtypes[256]; type specific mbuf allocations */ ); cyg_mempool_var_get_info( net_mem, &info ); diag_printf( "Misc mpool: total %7d, free %7d, max free block %d\n", info.totalmem, info.freemem, info.maxfree ); cyg_mempool_fix_get_info( net_mbufs, &info ); diag_printf( "Mbufs pool: total %7d, free %7d, blocksize %4d\n", info.totalmem, info.freemem, info.blocksize ); cyg_mempool_fix_get_info( net_clusters, &info ); diag_printf( "Clust pool: total %7d, free %7d, blocksize %4d\n", info.totalmem, info.freemem, info.blocksize );}// This API is for our own automated network tests. It's not in any header// files because it's not at all supported.int cyg_net_get_mem_stats( int which, cyg_mempool_info *p ){ CYG_CHECK_DATA_PTR( p, "Bad pointer to mempool_info" ); CYG_ASSERT( 0 <= which, "Mempool selector underflow" ); CYG_ASSERT( 2 >=which, "Mempool selector overflow" ); if ( p ) switch ( which ) { case 0: cyg_mempool_var_get_info( net_mem, p ); break; case 1: cyg_mempool_fix_get_info( net_mbufs, p ); break; case 2: cyg_mempool_fix_get_info( net_clusters, p ); break; default: return 0; } return (int)p;}intcyg_mtocl(u_long x){ int res; res = (((u_long)(x) - (u_long)mbutl) >> MCLSHIFT); return res;}struct mbuf *cyg_cltom(u_long x){ struct mbuf *res; res = (struct mbuf *)((caddr_t)((u_long)mbutl + ((u_long)(x) << MCLSHIFT))); return res;}externC void net_memcpy(void *d, void *s, int n){ START_STATS(); memcpy(d, s, n); FINISH_STATS(stats_memcpy);}externC void net_memset(void *s, int v, int n){ START_STATS(); memset(s, v, n); FINISH_STATS(stats_memset);}// Rather than bring in the whole BSD 'random' code...intarc4random(void){ cyg_uint32 res;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -