void radixsort(int* nums, int count) { int digit, max; Queue buckets[NDIGITS]; // One index per digit, including negatives // Don't bother working on one-element and empty array if (count < 2) return; for (int i = 0; i < NDIGITS; i++) { // Nullify each queue buckets[i].head = NULL; buckets[i].tail = NULL; } // Find the biggest number width max = radix_len(nums[0]); for (int i = 1; i < count; i++) if (radix_len(nums[i]) > max) max = radix_len(nums[i]); // Go through each column for (int i = 1; i <= max; i++) { // of each element for (int j = 0; j < count; j++) { // to get the i-th digit from j-th nums[] element, digit = radix_digit(nums[j], i) + BASE - 1; // compensate for negative digits // and enqueue it to the corresponding digit-th bucket. q_enq(buckets + digit, nums[j]); } // Take each element of nums[], for (int j = 0; j < count; j++) for (int k = 0; k < NDIGITS; k++) // and fill it with whatever while (buckets[k].head != NULL) // we find in each non-empty bucket. nums[j++] = q_deq(buckets + k); } }
void pktdemux() { PACKET pkt; NET ifc; /* interface packet came from */ IFMIB mib; int pkts; char * eth; pkts = 0; /* packets per loop */ while (rcvdq.q_len) { /* If we are low on free packets, don't hog CPU cycles */ if (pkts++ > bigfreeq.q_len) { #ifdef SUPERLOOP return; /* don't hog stack on superloop */ #else /* SUPERLOOP */ tk_yield(); /* let application tasks process received packets */ pkts = 0; /* reset counter */ #endif /* SUPERLOOP else */ } /* If we get receive interupt from the net during this lock, the MAC driver needs to wait or reschedule */ LOCK_NET_RESOURCE(RXQ_RESID); pkt = (PACKET)q_deq(&rcvdq); UNLOCK_NET_RESOURCE(RXQ_RESID); if (!pkt) panic("pktdemux: got null pkt"); ifc = pkt->net; mib = ifc->n_mib; /* maintain mib stats for unicast and broadcast */ if (isbcast(ifc, (u_char*)pkt->nb_buff + ETHHDR_BIAS)) mib->ifInNUcastPkts++; else mib->ifInUcastPkts++; if(mib->ifAdminStatus == NI_DOWN) { LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); /* dump packet from downed interface */ UNLOCK_NET_RESOURCE(FREEQ_RESID); mib->ifInDiscards++; continue; /* next packet */ } #ifdef NPDEBUG if (*(pkt->nb_buff - ALIGN_TYPE) != 'M' || *(pkt->nb_buff + pkt->nb_blen) != 'M') { dtrap(); panic("pktdemux: corrupt pkt"); } #endif /* NPDEBUG */ #ifdef LOSSY_IO if(NDEBUG & LOSSY_RX) { if(myloss()) { LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); /* punt packet */ UNLOCK_NET_RESOURCE(FREEQ_RESID); in_lastloss = (int)(cticks & 0x07) - 4; /* pseudo random reset */ continue; /* act as if we sent OK */ } } #endif /* LOSSY_IO */ /* see if driver set pkt->nb_prot and pkt->type */ if((ifc->n_flags & NF_NBPROT) == 0) { /* Set pkt->type and pkt->nb_prot based based on media type. * Some device drivers pass nb_plen as the total length of the * packet, while others subtract the MAC header. The latter is * probably the right thing to do, but because of this historic * inconsistency we don't try to fix it here - the longer size * turns out to be harmless since the IP layer fixes the size * based on the IP header length field. */ switch(ifc->n_mib->ifType) { case ETHERNET: /* get pointer to ethernet header */ eth = (pkt->nb_buff + ETHHDR_BIAS); #ifdef IEEE_802_3 /* see if it's got snap baggage */ if (ET_TYPE_GET(eth) <= 0x0600) { struct snap_hdr *snap; snap = (struct snap_hdr *)(pkt->nb_buff + ETHHDR_SIZE); pkt->type = (unshort)(snap->type); pkt->nb_prot = pkt->nb_buff + pkt->net->n_lnh; } else { pkt->type = htons((unshort)ET_TYPE_GET(eth)); pkt->nb_prot = pkt->nb_buff + ETHHDR_SIZE; } #else pkt->type = htons((unshort)ET_TYPE_GET(eth)); pkt->nb_prot = pkt->nb_buff + pkt->net->n_lnh; #endif /* IEEE_802_3 */ break; #if defined(USE_PPP) || defined(USE_SLIP) || defined(PROTOCOL_LIBS) case PPP: /* PPP or SLIP over a UART */ case SLIP: pkt->nb_prot = pkt->nb_buff + MaxLnh; pkt->type = IPTP; /* only type our PPP supports */ break; #endif /* USE_PPP || USE_SLIP */ #ifdef USE_PPPOE case PPPOE: /* do not change type yet, for PPPoE */ break; #endif /* USE_PPPOE */ default: /* driver bug? */ dprintf("pktdemux: bad Iface type %ld\n",ifc->n_mib->ifType); LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); UNLOCK_NET_RESOURCE(FREEQ_RESID); continue; } } /* pkt->nb_prot and pkt->type are now set. pass pkt to upper layer */ switch(pkt->type) { case IPTP: /* IP type */ LOCK_NET_RESOURCE(NET_RESID); #ifdef SHARED_IPADDRS add_share_route(pkt); #endif /* SHARED_IPADDRS */ #ifdef IP_V4 ip_rcv(pkt); #else /* don't care, it's IPv4 */ LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); UNLOCK_NET_RESOURCE(FREEQ_RESID); #endif UNLOCK_NET_RESOURCE(NET_RESID); break; #ifdef INCLUDE_ARP case ARPTP: /* ARP type */ LOCK_NET_RESOURCE(NET_RESID); arprcv(pkt); UNLOCK_NET_RESOURCE(NET_RESID); break; #endif /* INCLUDE_ARP */ #ifdef USE_PPPOE case htons(0x8863): case htons(0x8864): LOCK_NET_RESOURCE(NET_RESID); poe_rcv(pkt); UNLOCK_NET_RESOURCE(NET_RESID); break; #endif /* USE_PPPOE */ #ifdef IP_V6 case htons(0x86DD): /* Each received v6 pkt goes thru here exactly once, so set the * outer (first, and usually only) ipv6 header pointer. Tunneled headers * may exist further into the packet. */ pkt->ip6_hdr = (struct ipv6 *)pkt->nb_prot; LOCK_NET_RESOURCE(NET_RESID); ip6_rcv(pkt); UNLOCK_NET_RESOURCE(NET_RESID); break; #endif default: #ifdef NPDEBUG if (NDEBUG & UPCTRACE) dprintf("pktdemux: bad pkt type 0x%04x\n", ntohs(pkt->type)); #endif /* NPDEBUG */ ifc->n_mib->ifInUnknownProtos++; LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); /* return to free buffer */ UNLOCK_NET_RESOURCE(FREEQ_RESID); break; } continue; } }