updat code
This commit is contained in:
8
Makefile
8
Makefile
@@ -1,8 +1,10 @@
|
|||||||
|
|
||||||
BIN=smartdns
|
BIN=smartdns
|
||||||
OBJS=smartdns.o fast_ping.o
|
OBJS=smartdns.o fast_ping.o lib/bitops.o
|
||||||
CFLAGS=-g -O0
|
CFLAGS=-g -O0 -Wall
|
||||||
CFLAGS=-Iinclude
|
CFLAGS +=-Iinclude
|
||||||
|
CXXFLAGS=-g -O0 -Wall -std=c++11
|
||||||
|
CXXFLAGS +=-Iinclude
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
||||||
|
|||||||
111
fast_ping.c
111
fast_ping.c
@@ -2,6 +2,7 @@
|
|||||||
#include "atomic.h"
|
#include "atomic.h"
|
||||||
#include "hashtable.h"
|
#include "hashtable.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/icmp6.h>
|
#include <netinet/icmp6.h>
|
||||||
@@ -45,6 +46,10 @@ struct ping_host_struct {
|
|||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
unsigned int seq;
|
unsigned int seq;
|
||||||
|
struct timeval last;
|
||||||
|
int interval;
|
||||||
|
int timeout;
|
||||||
|
int send;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
socklen_t addr_len;
|
socklen_t addr_len;
|
||||||
struct fast_ping_packet packet;
|
struct fast_ping_packet packet;
|
||||||
@@ -54,7 +59,7 @@ struct fast_ping_struct {
|
|||||||
int run;
|
int run;
|
||||||
pthread_t tid;
|
pthread_t tid;
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
int ident;
|
unsigned short ident;
|
||||||
|
|
||||||
int epoll_fd;
|
int epoll_fd;
|
||||||
int fd_icmp;
|
int fd_icmp;
|
||||||
@@ -82,7 +87,7 @@ uint16_t _fast_ping_checksum(uint16_t *header, size_t len)
|
|||||||
return htons(~((sum >> 16) + (sum & 0xffff)));
|
return htons(~((sum >> 16) + (sum & 0xffff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int fast_ping_result_callback(fast_ping_result result)
|
void fast_ping_result_callback(fast_ping_result result)
|
||||||
{
|
{
|
||||||
ping_callback = result;
|
ping_callback = result;
|
||||||
}
|
}
|
||||||
@@ -148,7 +153,7 @@ void _fast_ping_install_filter_v4(int sock)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct addrinfo *_fast_ping_getaddr(const u_char *host, int type, int protocol)
|
static struct addrinfo *_fast_ping_getaddr(const char *host, int type, int protocol)
|
||||||
{
|
{
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *result = NULL;
|
struct addrinfo *result = NULL;
|
||||||
@@ -170,7 +175,7 @@ errout:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fast_ping_getdomain(const u_char *host)
|
static int _fast_ping_getdomain(const char *host)
|
||||||
{
|
{
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *result = NULL;
|
struct addrinfo *result = NULL;
|
||||||
@@ -197,12 +202,12 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fast_ping_host_get(struct ping_host_struct *ping_host)
|
static void _fast_ping_host_get(struct ping_host_struct *ping_host)
|
||||||
{
|
{
|
||||||
atomic_inc(&ping_host->ref);
|
atomic_inc(&ping_host->ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fast_ping_host_put(struct ping_host_struct *ping_host)
|
static void _fast_ping_host_put(struct ping_host_struct *ping_host)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&ping.map_lock);
|
pthread_mutex_lock(&ping.map_lock);
|
||||||
if (atomic_dec_and_test(&ping_host->ref)) {
|
if (atomic_dec_and_test(&ping_host->ref)) {
|
||||||
@@ -214,7 +219,7 @@ int _fast_ping_host_put(struct ping_host_struct *ping_host)
|
|||||||
pthread_mutex_unlock(&ping.map_lock);
|
pthread_mutex_unlock(&ping.map_lock);
|
||||||
|
|
||||||
if (ping_host == NULL) {
|
if (ping_host == NULL) {
|
||||||
return -1;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(ping_host);
|
free(ping_host);
|
||||||
@@ -280,34 +285,48 @@ errout:
|
|||||||
|
|
||||||
static int _fast_ping_sendping(struct ping_host_struct *ping_host)
|
static int _fast_ping_sendping(struct ping_host_struct *ping_host)
|
||||||
{
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
if (ping_host->type == AF_INET) {
|
if (ping_host->type == AF_INET) {
|
||||||
return _fast_ping_sendping_v4(ping_host);
|
ret = _fast_ping_sendping_v4(ping_host);
|
||||||
} else if (ping_host->type == AF_INET6) {
|
} else if (ping_host->type == AF_INET6) {
|
||||||
return _fast_ping_sendping_v6(ping_host);
|
ret = _fast_ping_sendping_v6(ping_host);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ping_host->send = 1;
|
||||||
|
gettimeofday(&ping_host->last, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fast_ping_create_sock(int protocol)
|
static int _fast_ping_create_sock(int protocol)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd = -1;
|
||||||
struct ping_host_struct *icmp_host = NULL;
|
struct ping_host_struct *icmp_host = NULL;
|
||||||
struct epoll_event event;
|
struct epoll_event event;
|
||||||
|
|
||||||
fd = socket(AF_INET, SOCK_RAW, protocol);
|
|
||||||
if (fd < 0) {
|
|
||||||
fprintf(stderr, "create icmp socket failed.\n");
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
case IPPROTO_ICMP:
|
case IPPROTO_ICMP:
|
||||||
|
fd = socket(AF_INET, SOCK_RAW, protocol);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "create icmp socket failed.\n");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
_fast_ping_install_filter_v4(fd);
|
_fast_ping_install_filter_v4(fd);
|
||||||
icmp_host = &ping.icmp_host;
|
icmp_host = &ping.icmp_host;
|
||||||
break;
|
break;
|
||||||
case IPPROTO_ICMPV6:
|
case IPPROTO_ICMPV6:
|
||||||
|
fd = socket(AF_INET6, SOCK_RAW, protocol);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "create icmp socket failed.\n");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
_fast_ping_install_filter_v6(fd);
|
_fast_ping_install_filter_v6(fd);
|
||||||
icmp_host = &ping.icmp_host;
|
icmp_host = &ping.icmp6_host;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,7 +390,6 @@ int fast_ping_start(const char *host, int timeout, void *userptr)
|
|||||||
struct addrinfo *gai = NULL;
|
struct addrinfo *gai = NULL;
|
||||||
int domain = -1;
|
int domain = -1;
|
||||||
int icmp_proto = 0;
|
int icmp_proto = 0;
|
||||||
char ip[PING_MAX_HOSTLEN];
|
|
||||||
uint32_t hostkey;
|
uint32_t hostkey;
|
||||||
uint32_t addrkey;
|
uint32_t addrkey;
|
||||||
|
|
||||||
@@ -402,17 +420,20 @@ int fast_ping_start(const char *host, int timeout, void *userptr)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(ping_host, 0, sizeof(ping_host));
|
int interval = 1000;
|
||||||
|
memset(ping_host, 0, sizeof(*ping_host));
|
||||||
strncpy(ping_host->host, host, PING_MAX_HOSTLEN);
|
strncpy(ping_host->host, host, PING_MAX_HOSTLEN);
|
||||||
ping_host->type = domain;
|
ping_host->type = domain;
|
||||||
ping_host->fd = _fast_ping_create_icmp(icmp_proto);
|
ping_host->fd = _fast_ping_create_icmp(icmp_proto);
|
||||||
|
ping_host->timeout = timeout;
|
||||||
|
ping_host->interval = interval;
|
||||||
memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen);
|
memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen);
|
||||||
ping_host->addr_len = gai->ai_addrlen;
|
ping_host->addr_len = gai->ai_addrlen;
|
||||||
|
|
||||||
atomic_set(&ping_host->ref, 0);
|
atomic_set(&ping_host->ref, 0);
|
||||||
|
|
||||||
hostkey = hash_string(ping_host->host);
|
hostkey = hash_string(ping_host->host);
|
||||||
addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0);
|
addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0);
|
||||||
pthread_mutex_lock(&ping.map_lock);
|
pthread_mutex_lock(&ping.map_lock);
|
||||||
_fast_ping_host_get(ping_host);
|
_fast_ping_host_get(ping_host);
|
||||||
hash_add(ping.hostmap, &ping_host->host_node, hostkey);
|
hash_add(ping.hostmap, &ping_host->host_node, hostkey);
|
||||||
@@ -467,12 +488,10 @@ void tv_sub(struct timeval *out, struct timeval *in)
|
|||||||
|
|
||||||
static int _fast_ping_icmp6_packet(struct ping_host_struct *ping_host, u_char *packet_data, int data_len, struct timeval *tvrecv)
|
static int _fast_ping_icmp6_packet(struct ping_host_struct *ping_host, u_char *packet_data, int data_len, struct timeval *tvrecv)
|
||||||
{
|
{
|
||||||
int hlen;
|
|
||||||
int icmp_len;
|
int icmp_len;
|
||||||
struct fast_ping_packet *packet = (struct fast_ping_packet *)packet_data;
|
struct fast_ping_packet *packet = (struct fast_ping_packet *)packet_data;
|
||||||
struct icmp6_hdr *icmp6 = &packet->icmp6;
|
struct icmp6_hdr *icmp6 = &packet->icmp6;
|
||||||
struct timeval tvresult = *tvrecv;
|
struct timeval tvresult = *tvrecv;
|
||||||
double rtt;
|
|
||||||
|
|
||||||
if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) {
|
if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -489,7 +508,7 @@ static int _fast_ping_icmp6_packet(struct ping_host_struct *ping_host, u_char *p
|
|||||||
|
|
||||||
struct timeval *tvsend = &packet->msg.tv;
|
struct timeval *tvsend = &packet->msg.tv;
|
||||||
tv_sub(&tvresult, tvsend);
|
tv_sub(&tvresult, tvsend);
|
||||||
ping_callback(ping_host->host, ping_host->seq, &tvresult, ping_host->userptr);
|
ping_callback(ping_host->host, PING_RESULT_RESPONSE, ping_host->seq, &tvresult, ping_host->userptr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -527,7 +546,7 @@ static int _fast_ping_icmp_packet(struct ping_host_struct *ping_host, u_char *pa
|
|||||||
struct timeval *tvsend = &packet->msg.tv;
|
struct timeval *tvsend = &packet->msg.tv;
|
||||||
tv_sub(&tvresult, tvsend);
|
tv_sub(&tvresult, tvsend);
|
||||||
|
|
||||||
ping_callback(ping_host->host, ping_host->seq, &tvresult, ping_host->userptr);
|
ping_callback(ping_host->host, PING_RESULT_RESPONSE, ping_host->seq, &tvresult, ping_host->userptr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -551,14 +570,7 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fast_ping_create_tcp(struct ping_host_struct *ping_host)
|
static int _fast_ping_gethost_by_addr(char *host, struct sockaddr *addr, socklen_t addr_len)
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _fast_ping_ping_host(struct ping_host_struct *ping_host) {}
|
|
||||||
|
|
||||||
static int _fast_ping_gethost_by_addr(u_char *host, struct sockaddr *addr, socklen_t addr_len)
|
|
||||||
{
|
{
|
||||||
struct sockaddr_storage *addr_store = (struct sockaddr_storage *)addr;
|
struct sockaddr_storage *addr_store = (struct sockaddr_storage *)addr;
|
||||||
host[0] = 0;
|
host[0] = 0;
|
||||||
@@ -603,7 +615,7 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
addrkey = jhash(&from, from_len, 0);
|
addrkey = jhash(&from, from_len, 0);
|
||||||
pthread_mutex_lock(&ping.map_lock);
|
pthread_mutex_lock(&ping.map_lock);
|
||||||
hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey)
|
hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey)
|
||||||
{
|
{
|
||||||
@@ -617,6 +629,8 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recv_ping_host->send = 0;
|
||||||
|
|
||||||
_fast_ping_recvping(recv_ping_host, inpacket, len, now);
|
_fast_ping_recvping(recv_ping_host, inpacket, len, now);
|
||||||
return 0;
|
return 0;
|
||||||
errout:
|
errout:
|
||||||
@@ -628,10 +642,24 @@ static void _fast_ping_period_run()
|
|||||||
struct ping_host_struct *ping_host;
|
struct ping_host_struct *ping_host;
|
||||||
struct hlist_node *tmp;
|
struct hlist_node *tmp;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
struct timeval now;
|
||||||
|
struct timeval interval;
|
||||||
|
uint64_t millisecond;
|
||||||
|
gettimeofday(&now, 0);
|
||||||
|
|
||||||
pthread_mutex_lock(&ping.map_lock);
|
pthread_mutex_lock(&ping.map_lock);
|
||||||
hash_for_each_safe(ping.addrmap, i, tmp, ping_host, addr_node)
|
hash_for_each_safe(ping.addrmap, i, tmp, ping_host, addr_node)
|
||||||
{
|
{
|
||||||
_fast_ping_sendping(ping_host);
|
interval = now;
|
||||||
|
tv_sub(&interval, &ping_host->last);
|
||||||
|
millisecond = interval.tv_sec * 1000 + interval.tv_usec / 1000;
|
||||||
|
if (millisecond > ping_host->timeout && ping_host->send == 1) {
|
||||||
|
ping_callback(ping_host->host, PING_RESULT_TIMEOUT, ping_host->seq, &interval, ping_host->userptr);
|
||||||
|
ping_host->send = 0;
|
||||||
|
}
|
||||||
|
if (millisecond >= ping_host->interval) {
|
||||||
|
_fast_ping_sendping(ping_host);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&ping.map_lock);
|
pthread_mutex_unlock(&ping.map_lock);
|
||||||
}
|
}
|
||||||
@@ -643,14 +671,19 @@ static void *_fast_ping_work(void *arg)
|
|||||||
int i;
|
int i;
|
||||||
struct timeval last = { 0 };
|
struct timeval last = { 0 };
|
||||||
struct timeval now = { 0 };
|
struct timeval now = { 0 };
|
||||||
|
struct timeval diff = {0};
|
||||||
|
uint millisec = 0;
|
||||||
|
|
||||||
while (ping.run) {
|
while (ping.run) {
|
||||||
if (last.tv_sec != now.tv_sec) {
|
diff = now;
|
||||||
|
tv_sub(&diff, &last);
|
||||||
|
millisec = diff.tv_sec * 1000 + diff.tv_usec / 1000;
|
||||||
|
if (millisec >= 100) {
|
||||||
_fast_ping_period_run();
|
_fast_ping_period_run();
|
||||||
last = now;
|
last = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
num = epoll_wait(ping.epoll_fd, events, PING_MAX_EVENTS, 1000);
|
num = epoll_wait(ping.epoll_fd, events, PING_MAX_EVENTS, 100);
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
gettimeofday(&now, 0);
|
gettimeofday(&now, 0);
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
@@ -727,7 +760,7 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fast_ping_exit()
|
void fast_ping_exit()
|
||||||
{
|
{
|
||||||
if (ping.tid > 0) {
|
if (ping.tid > 0) {
|
||||||
void *ret = NULL;
|
void *ret = NULL;
|
||||||
@@ -737,12 +770,12 @@ int fast_ping_exit()
|
|||||||
|
|
||||||
if (ping.fd_icmp > 0) {
|
if (ping.fd_icmp > 0) {
|
||||||
close(ping.fd_icmp);
|
close(ping.fd_icmp);
|
||||||
ping.fd_icmp < 0;
|
ping.fd_icmp = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ping.fd_icmp6 > 0) {
|
if (ping.fd_icmp6 > 0) {
|
||||||
close(ping.fd_icmp6);
|
close(ping.fd_icmp6);
|
||||||
ping.fd_icmp6 < 0;
|
ping.fd_icmp6 = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_destroy(&ping.lock);
|
pthread_mutex_destroy(&ping.lock);
|
||||||
|
|||||||
11
fast_ping.h
11
fast_ping.h
@@ -13,8 +13,13 @@ typedef enum {
|
|||||||
FAST_PING_UDP
|
FAST_PING_UDP
|
||||||
} FAST_PING_TYPE;
|
} FAST_PING_TYPE;
|
||||||
|
|
||||||
typedef void (*fast_ping_result)(const char *host, int seqno, struct timeval *tv, void *userptr);
|
typedef enum {
|
||||||
int fast_ping_result_callback(fast_ping_result result);
|
PING_RESULT_RESPONSE = 1,
|
||||||
|
PING_RESULT_TIMEOUT = 2,
|
||||||
|
} FAST_PING_RESULT;
|
||||||
|
|
||||||
|
typedef void (*fast_ping_result)(const char *host, FAST_PING_RESULT result, int seqno, struct timeval *tv, void *userptr);
|
||||||
|
void fast_ping_result_callback(fast_ping_result result);
|
||||||
|
|
||||||
int fast_ping_start(const char *host, int timeout, void *userptr);
|
int fast_ping_start(const char *host, int timeout, void *userptr);
|
||||||
|
|
||||||
@@ -22,7 +27,7 @@ int fast_ping_stop(const char *host);
|
|||||||
|
|
||||||
int fast_ping_init();
|
int fast_ping_init();
|
||||||
|
|
||||||
int fast_ping_exit();
|
void fast_ping_exit();
|
||||||
|
|
||||||
#ifdef __cpluscplus
|
#ifdef __cpluscplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#ifndef _GENERIC_ATOMIC_H
|
#ifndef _GENERIC_ATOMIC_H
|
||||||
#define _GENERIC_ATOMIC_H
|
#define _GENERIC_ATOMIC_H
|
||||||
|
|
||||||
|
|
||||||
/* Check GCC version, just to be safe */
|
/* Check GCC version, just to be safe */
|
||||||
#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 1)
|
#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 1)
|
||||||
# error atomic.h works only with GCC newer than version 4.1
|
# error atomic.h works only with GCC newer than version 4.1
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "bitops.h"
|
#include "bitops.h"
|
||||||
|
#include "findbit.h"
|
||||||
|
|
||||||
|
|
||||||
#define DECLARE_BITMAP(name,bits) \
|
#define DECLARE_BITMAP(name,bits) \
|
||||||
unsigned long name[BITS_TO_LONGS(bits)]
|
unsigned long name[BITS_TO_LONGS(bits)]
|
||||||
@@ -101,7 +103,7 @@ static inline int test_and_set_bit(int nr, unsigned long *addr)
|
|||||||
*/
|
*/
|
||||||
static inline unsigned long *bitmap_alloc(int nbits)
|
static inline unsigned long *bitmap_alloc(int nbits)
|
||||||
{
|
{
|
||||||
return calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long));
|
return (unsigned long *)calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
162
include/bitops.h
162
include/bitops.h
@@ -2,6 +2,10 @@
|
|||||||
#ifndef _GENERIC_BITOPS_H_
|
#ifndef _GENERIC_BITOPS_H_
|
||||||
#define _GENERIC_BITOPS_H_
|
#define _GENERIC_BITOPS_H_
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "gcc_builtin.h"
|
||||||
|
|
||||||
#ifndef __WORDSIZE
|
#ifndef __WORDSIZE
|
||||||
#define __WORDSIZE (__SIZEOF_LONG__ * 8)
|
#define __WORDSIZE (__SIZEOF_LONG__ * 8)
|
||||||
#endif
|
#endif
|
||||||
@@ -24,6 +28,164 @@ extern unsigned int __sw_hweight32(unsigned int w);
|
|||||||
extern unsigned long __sw_hweight64(uint64_t w);
|
extern unsigned long __sw_hweight64(uint64_t w);
|
||||||
|
|
||||||
|
|
||||||
|
#define ffz(x) __ffs(~(x))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fls - find last (most-significant) bit set
|
||||||
|
* @x: the word to search
|
||||||
|
*
|
||||||
|
* This is defined the same way as ffs.
|
||||||
|
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __ffs - find first bit in word.
|
||||||
|
* @word: The word to search
|
||||||
|
*
|
||||||
|
* Undefined if no bit exists, so code should check against 0 first.
|
||||||
|
*/
|
||||||
|
static inline unsigned long __ffs(unsigned long word)
|
||||||
|
{
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
#if __BITS_PER_LONG == 64
|
||||||
|
if ((word & 0xffffffff) == 0) {
|
||||||
|
num += 32;
|
||||||
|
word >>= 32;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if ((word & 0xffff) == 0) {
|
||||||
|
num += 16;
|
||||||
|
word >>= 16;
|
||||||
|
}
|
||||||
|
if ((word & 0xff) == 0) {
|
||||||
|
num += 8;
|
||||||
|
word >>= 8;
|
||||||
|
}
|
||||||
|
if ((word & 0xf) == 0) {
|
||||||
|
num += 4;
|
||||||
|
word >>= 4;
|
||||||
|
}
|
||||||
|
if ((word & 0x3) == 0) {
|
||||||
|
num += 2;
|
||||||
|
word >>= 2;
|
||||||
|
}
|
||||||
|
if ((word & 0x1) == 0)
|
||||||
|
num += 1;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fls(int x)
|
||||||
|
{
|
||||||
|
int r = 32;
|
||||||
|
|
||||||
|
if (!x)
|
||||||
|
return 0;
|
||||||
|
if (!(x & 0xffff0000u)) {
|
||||||
|
x <<= 16;
|
||||||
|
r -= 16;
|
||||||
|
}
|
||||||
|
if (!(x & 0xff000000u)) {
|
||||||
|
x <<= 8;
|
||||||
|
r -= 8;
|
||||||
|
}
|
||||||
|
if (!(x & 0xf0000000u)) {
|
||||||
|
x <<= 4;
|
||||||
|
r -= 4;
|
||||||
|
}
|
||||||
|
if (!(x & 0xc0000000u)) {
|
||||||
|
x <<= 2;
|
||||||
|
r -= 2;
|
||||||
|
}
|
||||||
|
if (!(x & 0x80000000u)) {
|
||||||
|
x <<= 1;
|
||||||
|
r -= 1;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fls64 - find last set bit in a 64-bit word
|
||||||
|
* @x: the word to search
|
||||||
|
*
|
||||||
|
* This is defined in a similar way as the libc and compiler builtin
|
||||||
|
* ffsll, but returns the position of the most significant set bit.
|
||||||
|
*
|
||||||
|
* fls64(value) returns 0 if value is 0 or the position of the last
|
||||||
|
* set bit if value is nonzero. The last (most significant) bit is
|
||||||
|
* at position 64.
|
||||||
|
*/
|
||||||
|
#if BITS_PER_LONG == 32
|
||||||
|
static inline int fls64(uint64_t x)
|
||||||
|
{
|
||||||
|
uint32_t h = x >> 32;
|
||||||
|
if (h)
|
||||||
|
return fls(h) + 32;
|
||||||
|
return fls(x);
|
||||||
|
}
|
||||||
|
#elif BITS_PER_LONG == 64
|
||||||
|
static inline int fls64(uint64_t x)
|
||||||
|
{
|
||||||
|
if (x == 0)
|
||||||
|
return 0;
|
||||||
|
return __fls(x) + 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error BITS_PER_LONG not 32 or 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hweightN - returns the hamming weight of a N-bit word
|
||||||
|
* @x: the word to weigh
|
||||||
|
*
|
||||||
|
* The Hamming Weight of a number is the total number of bits set in it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline unsigned int hweight32(unsigned int w)
|
||||||
|
{
|
||||||
|
unsigned int res = w - ((w >> 1) & 0x55555555);
|
||||||
|
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
|
||||||
|
res = (res + (res >> 4)) & 0x0F0F0F0F;
|
||||||
|
res = res + (res >> 8);
|
||||||
|
return (res + (res >> 16)) & 0x000000FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int hweight16(unsigned int w)
|
||||||
|
{
|
||||||
|
unsigned int res = w - ((w >> 1) & 0x5555);
|
||||||
|
res = (res & 0x3333) + ((res >> 2) & 0x3333);
|
||||||
|
res = (res + (res >> 4)) & 0x0F0F;
|
||||||
|
return (res + (res >> 8)) & 0x00FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int hweight8(unsigned int w)
|
||||||
|
{
|
||||||
|
unsigned int res = w - ((w >> 1) & 0x55);
|
||||||
|
res = (res & 0x33) + ((res >> 2) & 0x33);
|
||||||
|
return (res + (res >> 4)) & 0x0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned long hweight64(uint64_t w)
|
||||||
|
{
|
||||||
|
#if BITS_PER_LONG == 32
|
||||||
|
return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
|
||||||
|
#elif BITS_PER_LONG == 64
|
||||||
|
#ifdef ARCH_HAS_FAST_MULTIPLIER
|
||||||
|
w -= (w >> 1) & 0x5555555555555555ul;
|
||||||
|
w = (w & 0x3333333333333333ul) + ((w >> 2) & 0x3333333333333333ul);
|
||||||
|
w = (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0ful;
|
||||||
|
return (w * 0x0101010101010101ul) >> 56;
|
||||||
|
#else
|
||||||
|
uint64_t res = w - ((w >> 1) & 0x5555555555555555ul);
|
||||||
|
res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
|
||||||
|
res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
|
||||||
|
res = res + (res >> 8);
|
||||||
|
res = res + (res >> 16);
|
||||||
|
return (res + (res >> 32)) & 0x00000000000000FFul;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#define for_each_set_bit(bit, addr, size) \
|
#define for_each_set_bit(bit, addr, size) \
|
||||||
for ((bit) = find_first_bit((addr), (size)); \
|
for ((bit) = find_first_bit((addr), (size)); \
|
||||||
(bit) < (size); \
|
(bit) < (size); \
|
||||||
|
|||||||
78
include/findbit.h
Normal file
78
include/findbit.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_
|
||||||
|
#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_
|
||||||
|
|
||||||
|
#ifndef find_next_bit
|
||||||
|
/**
|
||||||
|
* find_next_bit - find the next set bit in a memory region
|
||||||
|
* @addr: The address to base the search on
|
||||||
|
* @offset: The bitnumber to start searching at
|
||||||
|
* @size: The bitmap size in bits
|
||||||
|
*
|
||||||
|
* Returns the bit number for the next set bit
|
||||||
|
* If no bits are set, returns @size.
|
||||||
|
*/
|
||||||
|
extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
|
||||||
|
size, unsigned long offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef find_next_and_bit
|
||||||
|
/**
|
||||||
|
* find_next_and_bit - find the next set bit in both memory regions
|
||||||
|
* @addr1: The first address to base the search on
|
||||||
|
* @addr2: The second address to base the search on
|
||||||
|
* @offset: The bitnumber to start searching at
|
||||||
|
* @size: The bitmap size in bits
|
||||||
|
*
|
||||||
|
* Returns the bit number for the next set bit
|
||||||
|
* If no bits are set, returns @size.
|
||||||
|
*/
|
||||||
|
extern unsigned long find_next_and_bit(const unsigned long *addr1,
|
||||||
|
const unsigned long *addr2, unsigned long size,
|
||||||
|
unsigned long offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef find_next_zero_bit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_next_zero_bit - find the next cleared bit in a memory region
|
||||||
|
* @addr: The address to base the search on
|
||||||
|
* @offset: The bitnumber to start searching at
|
||||||
|
* @size: The bitmap size in bits
|
||||||
|
*
|
||||||
|
* Returns the bit number of the next zero bit
|
||||||
|
* If no bits are zero, returns @size.
|
||||||
|
*/
|
||||||
|
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
|
||||||
|
unsigned long offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef find_first_bit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_first_bit - find the first set bit in a memory region
|
||||||
|
* @addr: The address to start the search at
|
||||||
|
* @size: The maximum number of bits to search
|
||||||
|
*
|
||||||
|
* Returns the bit number of the first set bit.
|
||||||
|
* If no bits are set, returns @size.
|
||||||
|
*/
|
||||||
|
extern unsigned long find_first_bit(const unsigned long *addr,
|
||||||
|
unsigned long size);
|
||||||
|
|
||||||
|
#endif /* find_first_bit */
|
||||||
|
|
||||||
|
#ifndef find_first_zero_bit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_first_zero_bit - find the first cleared bit in a memory region
|
||||||
|
* @addr: The address to start the search at
|
||||||
|
* @size: The maximum number of bits to search
|
||||||
|
*
|
||||||
|
* Returns the bit number of the first cleared bit.
|
||||||
|
* If no bits are zero, returns @size.
|
||||||
|
*/
|
||||||
|
unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ */
|
||||||
118
include/gcc_builtin.h
Normal file
118
include/gcc_builtin.h
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef _TOOLS_LINUX_COMPILER_H_
|
||||||
|
#define _TOOLS_LINUX_COMPILER_H_
|
||||||
|
|
||||||
|
#ifndef __compiletime_error
|
||||||
|
# define __compiletime_error(message)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Optimization barrier */
|
||||||
|
/* The "volatile" is due to gcc bugs */
|
||||||
|
#define barrier() __asm__ __volatile__("": : :"memory")
|
||||||
|
|
||||||
|
#ifndef __always_inline
|
||||||
|
# define __always_inline inline __attribute__((always_inline))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef noinline
|
||||||
|
#define noinline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Are two types/vars the same type (ignoring qualifiers)? */
|
||||||
|
#ifndef __same_type
|
||||||
|
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
/*
|
||||||
|
* FIXME: Big hammer to get rid of tons of:
|
||||||
|
* "warning: always_inline function might not be inlinable"
|
||||||
|
*
|
||||||
|
* At least on android-ndk-r12/platforms/android-24/arch-arm
|
||||||
|
*/
|
||||||
|
#undef __always_inline
|
||||||
|
#define __always_inline inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __user
|
||||||
|
#define __rcu
|
||||||
|
#define __read_mostly
|
||||||
|
|
||||||
|
#ifndef __attribute_const__
|
||||||
|
# define __attribute_const__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __maybe_unused
|
||||||
|
# define __maybe_unused __attribute__((unused))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __used
|
||||||
|
# define __used __attribute__((__unused__))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __packed
|
||||||
|
# define __packed __attribute__((__packed__))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __force
|
||||||
|
# define __force
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __weak
|
||||||
|
# define __weak __attribute__((weak))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef likely
|
||||||
|
# define likely(x) __builtin_expect(!!(x), 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef unlikely
|
||||||
|
# define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __init
|
||||||
|
# define __init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef noinline
|
||||||
|
# define noinline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define uninitialized_var(x) x = *(&(x))
|
||||||
|
|
||||||
|
#ifndef __fallthrough
|
||||||
|
# define __fallthrough
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
|
||||||
|
|
||||||
|
#ifndef max
|
||||||
|
#define max(x, y) ({ \
|
||||||
|
typeof(x) _max1 = (x); \
|
||||||
|
typeof(y) _max2 = (y); \
|
||||||
|
(void) (&_max1 == &_max2); \
|
||||||
|
_max1 > _max2 ? _max1 : _max2; })
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
#define min(x, y) ({ \
|
||||||
|
typeof(x) _min1 = (x); \
|
||||||
|
typeof(y) _min2 = (y); \
|
||||||
|
(void) (&_min1 == &_min2); \
|
||||||
|
_min1 < _min2 ? _min1 : _min2; })
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef roundup
|
||||||
|
#define roundup(x, y) ( \
|
||||||
|
{ \
|
||||||
|
const typeof(y) __y = y; \
|
||||||
|
(((x) + (__y - 1)) / __y) * __y; \
|
||||||
|
} \
|
||||||
|
)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __round_mask(x, y) ((__typeof__(x))((y)-1))
|
||||||
|
#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
|
||||||
|
#define round_down(x, y) ((x) & ~__round_mask(x, y))
|
||||||
|
|
||||||
|
#endif /* _TOOLS_LINUX_COMPILER_H */
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef _GENERIC_HASH_H
|
#ifndef _GENERIC_HASH_H
|
||||||
#define _GENERIC_HASH_H
|
#define _GENERIC_HASH_H
|
||||||
|
|
||||||
|
#include "bitmap.h"
|
||||||
#include "jhash.h"
|
#include "jhash.h"
|
||||||
|
|
||||||
/* Fast hashing routine for ints, longs and pointers.
|
/* Fast hashing routine for ints, longs and pointers.
|
||||||
@@ -113,6 +114,17 @@ int __ilog2_u64(uint64_t n)
|
|||||||
__ilog2_u64(n) \
|
__ilog2_u64(n) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#if BITS_PER_LONG == 32
|
||||||
|
#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_32
|
||||||
|
#define hash_long(val, bits) hash_32(val, bits)
|
||||||
|
#elif BITS_PER_LONG == 64
|
||||||
|
#define hash_long(val, bits) hash_64(val, bits)
|
||||||
|
#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_64
|
||||||
|
#else
|
||||||
|
#error Wordsize not 32 or 64
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This hash multiplies the input by a large odd number and takes the
|
* This hash multiplies the input by a large odd number and takes the
|
||||||
* high bits. Since multiplication propagates changes to the most
|
* high bits. Since multiplication propagates changes to the most
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "bitmap.h"
|
|
||||||
|
|
||||||
#ifndef __same_type
|
#ifndef __same_type
|
||||||
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
|
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
|
||||||
@@ -149,5 +148,4 @@ static inline void hash_del(struct hlist_node *node)
|
|||||||
hlist_for_each_entry_safe(obj, tmp,\
|
hlist_for_each_entry_safe(obj, tmp,\
|
||||||
&name[hash_min(key, HASH_BITS(name))], member)
|
&name[hash_min(key, HASH_BITS(name))], member)
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -79,7 +79,7 @@ static inline uint32_t __get_unaligned_cpu32(const void *p)
|
|||||||
static inline uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
|
static inline uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
|
||||||
{
|
{
|
||||||
uint32_t a, b, c;
|
uint32_t a, b, c;
|
||||||
const uint8_t *k = key;
|
const uint8_t *k = (uint8_t *)key;
|
||||||
|
|
||||||
/* Set up the internal state */
|
/* Set up the internal state */
|
||||||
a = b = c = JHASH_INITVAL + length + initval;
|
a = b = c = JHASH_INITVAL + length + initval;
|
||||||
|
|||||||
@@ -60,46 +60,46 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert a new entry between two known consecutive entries.
|
* Insert a add entry between two known consecutive entries.
|
||||||
*
|
*
|
||||||
* This is only for internal list manipulation where we know
|
* This is only for internal list manipulation where we know
|
||||||
* the prev/next entries already!
|
* the prev/next entries already!
|
||||||
*/
|
*/
|
||||||
static inline void __list_add(struct list_head *new,
|
static inline void __list_add(struct list_head *add,
|
||||||
struct list_head *prev,
|
struct list_head *prev,
|
||||||
struct list_head *next)
|
struct list_head *next)
|
||||||
{
|
{
|
||||||
next->prev = new;
|
next->prev = add;
|
||||||
new->next = next;
|
add->next = next;
|
||||||
new->prev = prev;
|
add->prev = prev;
|
||||||
prev->next = new;
|
prev->next = add;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_add - add a new entry
|
* list_add - add a add entry
|
||||||
* @new: new entry to be added
|
* @add: add entry to be added
|
||||||
* @head: list head to add it after
|
* @head: list head to add it after
|
||||||
*
|
*
|
||||||
* Insert a new entry after the specified head.
|
* Insert a add entry after the specified head.
|
||||||
* This is good for implementing stacks.
|
* This is good for implementing stacks.
|
||||||
*/
|
*/
|
||||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
static inline void list_add(struct list_head *add, struct list_head *head)
|
||||||
{
|
{
|
||||||
__list_add(new, head, head->next);
|
__list_add(add, head, head->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_add_tail - add a new entry
|
* list_add_tail - add a add entry
|
||||||
* @new: new entry to be added
|
* @add: add entry to be added
|
||||||
* @head: list head to add it before
|
* @head: list head to add it before
|
||||||
*
|
*
|
||||||
* Insert a new entry before the specified head.
|
* Insert a add entry before the specified head.
|
||||||
* This is useful for implementing queues.
|
* This is useful for implementing queues.
|
||||||
*/
|
*/
|
||||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
static inline void list_add_tail(struct list_head *add, struct list_head *head)
|
||||||
{
|
{
|
||||||
__list_add(new, head->prev, head);
|
__list_add(add, head->prev, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -129,30 +129,30 @@ static inline void __list_del_entry(struct list_head *entry)
|
|||||||
static inline void list_del(struct list_head *entry)
|
static inline void list_del(struct list_head *entry)
|
||||||
{
|
{
|
||||||
__list_del(entry->prev, entry->next);
|
__list_del(entry->prev, entry->next);
|
||||||
entry->next = LIST_POISON1;
|
entry->next = (struct list_head *)LIST_POISON1;
|
||||||
entry->prev = LIST_POISON2;
|
entry->prev = (struct list_head *)LIST_POISON2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_replace - replace old entry by new one
|
* list_replace - replace old entry by add one
|
||||||
* @old : the element to be replaced
|
* @old : the element to be replaced
|
||||||
* @new : the new element to insert
|
* @add : the add element to insert
|
||||||
*
|
*
|
||||||
* If @old was empty, it will be overwritten.
|
* If @old was empty, it will be overwritten.
|
||||||
*/
|
*/
|
||||||
static inline void list_replace(struct list_head *old,
|
static inline void list_replace(struct list_head *old,
|
||||||
struct list_head *new)
|
struct list_head *add)
|
||||||
{
|
{
|
||||||
new->next = old->next;
|
add->next = old->next;
|
||||||
new->next->prev = new;
|
add->next->prev = add;
|
||||||
new->prev = old->prev;
|
add->prev = old->prev;
|
||||||
new->prev->next = new;
|
add->prev->next = add;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void list_replace_init(struct list_head *old,
|
static inline void list_replace_init(struct list_head *old,
|
||||||
struct list_head *new)
|
struct list_head *add)
|
||||||
{
|
{
|
||||||
list_replace(old, new);
|
list_replace(old, add);
|
||||||
INIT_LIST_HEAD(old);
|
INIT_LIST_HEAD(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +265,7 @@ static inline void __list_cut_position(struct list_head *list,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* list_cut_position - cut a list into two
|
* list_cut_position - cut a list into two
|
||||||
* @list: a new list to add all removed entries
|
* @list: a add list to add all removed entries
|
||||||
* @head: a list with entries
|
* @head: a list with entries
|
||||||
* @entry: an entry within head, could be the head itself
|
* @entry: an entry within head, could be the head itself
|
||||||
* and if so we won't cut the list
|
* and if so we won't cut the list
|
||||||
@@ -307,7 +307,7 @@ static inline void __list_splice(const struct list_head *list,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* list_splice - join two lists, this is designed for stacks
|
* list_splice - join two lists, this is designed for stacks
|
||||||
* @list: the new list to add.
|
* @list: the add list to add.
|
||||||
* @head: the place to add it in the first list.
|
* @head: the place to add it in the first list.
|
||||||
*/
|
*/
|
||||||
static inline void list_splice(const struct list_head *list,
|
static inline void list_splice(const struct list_head *list,
|
||||||
@@ -319,7 +319,7 @@ static inline void list_splice(const struct list_head *list,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* list_splice_tail - join two lists, each list being a queue
|
* list_splice_tail - join two lists, each list being a queue
|
||||||
* @list: the new list to add.
|
* @list: the add list to add.
|
||||||
* @head: the place to add it in the first list.
|
* @head: the place to add it in the first list.
|
||||||
*/
|
*/
|
||||||
static inline void list_splice_tail(struct list_head *list,
|
static inline void list_splice_tail(struct list_head *list,
|
||||||
@@ -331,7 +331,7 @@ static inline void list_splice_tail(struct list_head *list,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||||
* @list: the new list to add.
|
* @list: the add list to add.
|
||||||
* @head: the place to add it in the first list.
|
* @head: the place to add it in the first list.
|
||||||
*
|
*
|
||||||
* The list at @list is reinitialised
|
* The list at @list is reinitialised
|
||||||
@@ -347,7 +347,7 @@ static inline void list_splice_init(struct list_head *list,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* list_splice_tail_init - join two lists and reinitialise the emptied list
|
* list_splice_tail_init - join two lists and reinitialise the emptied list
|
||||||
* @list: the new list to add.
|
* @list: the add list to add.
|
||||||
* @head: the place to add it in the first list.
|
* @head: the place to add it in the first list.
|
||||||
*
|
*
|
||||||
* Each of the lists is a queue.
|
* Each of the lists is a queue.
|
||||||
@@ -644,8 +644,8 @@ static inline void __hlist_del(struct hlist_node *n)
|
|||||||
static inline void hlist_del(struct hlist_node *n)
|
static inline void hlist_del(struct hlist_node *n)
|
||||||
{
|
{
|
||||||
__hlist_del(n);
|
__hlist_del(n);
|
||||||
n->next = LIST_POISON1;
|
n->next = (struct hlist_node *)LIST_POISON1;
|
||||||
n->pprev = LIST_POISON2;
|
n->pprev = (struct hlist_node **)LIST_POISON2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void hlist_del_init(struct hlist_node *n)
|
static inline void hlist_del_init(struct hlist_node *n)
|
||||||
@@ -703,11 +703,11 @@ static inline bool hlist_fake(struct hlist_node *h)
|
|||||||
* reference of the first entry if it exists.
|
* reference of the first entry if it exists.
|
||||||
*/
|
*/
|
||||||
static inline void hlist_move_list(struct hlist_head *old,
|
static inline void hlist_move_list(struct hlist_head *old,
|
||||||
struct hlist_head *new)
|
struct hlist_head *add)
|
||||||
{
|
{
|
||||||
new->first = old->first;
|
add->first = old->first;
|
||||||
if (new->first)
|
if (add->first)
|
||||||
new->first->pprev = &new->first;
|
add->first->pprev = &add->first;
|
||||||
old->first = NULL;
|
old->first = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
154
lib/bitops.c
Normal file
154
lib/bitops.c
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
|
||||||
|
#include "bitmap.h"
|
||||||
|
#include "bitops.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a common helper function for find_next_bit, find_next_zero_bit, and
|
||||||
|
* find_next_and_bit. The differences are:
|
||||||
|
* - The "invert" argument, which is XORed with each fetched word before
|
||||||
|
* searching it for one bits.
|
||||||
|
* - The optional "addr2", which is anded with "addr1" if present.
|
||||||
|
*/
|
||||||
|
static inline unsigned long _find_next_bit(const unsigned long *addr1,
|
||||||
|
const unsigned long *addr2, unsigned long nbits,
|
||||||
|
unsigned long start, unsigned long invert)
|
||||||
|
{
|
||||||
|
unsigned long tmp;
|
||||||
|
|
||||||
|
if (unlikely(start >= nbits))
|
||||||
|
return nbits;
|
||||||
|
|
||||||
|
tmp = addr1[start / BITS_PER_LONG];
|
||||||
|
if (addr2)
|
||||||
|
tmp &= addr2[start / BITS_PER_LONG];
|
||||||
|
tmp ^= invert;
|
||||||
|
|
||||||
|
/* Handle 1st word. */
|
||||||
|
tmp &= BITMAP_FIRST_WORD_MASK(start);
|
||||||
|
start = round_down(start, BITS_PER_LONG);
|
||||||
|
|
||||||
|
while (!tmp) {
|
||||||
|
start += BITS_PER_LONG;
|
||||||
|
if (start >= nbits)
|
||||||
|
return nbits;
|
||||||
|
|
||||||
|
tmp = addr1[start / BITS_PER_LONG];
|
||||||
|
if (addr2)
|
||||||
|
tmp &= addr2[start / BITS_PER_LONG];
|
||||||
|
tmp ^= invert;
|
||||||
|
}
|
||||||
|
|
||||||
|
return min(start + __ffs(tmp), nbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the next set bit in a memory region.
|
||||||
|
*/
|
||||||
|
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
|
||||||
|
unsigned long offset)
|
||||||
|
{
|
||||||
|
return _find_next_bit(addr, NULL, size, offset, 0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the first set bit in a memory region.
|
||||||
|
*/
|
||||||
|
unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
|
||||||
|
{
|
||||||
|
unsigned long idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
|
||||||
|
if (addr[idx])
|
||||||
|
return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the first cleared bit in a memory region.
|
||||||
|
*/
|
||||||
|
unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
|
||||||
|
{
|
||||||
|
unsigned long idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
|
||||||
|
if (addr[idx] != ~0UL)
|
||||||
|
return min(idx * BITS_PER_LONG + ffz(addr[idx]), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
|
||||||
|
unsigned long offset)
|
||||||
|
{
|
||||||
|
return _find_next_bit(addr, NULL, size, offset, ~0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long find_next_and_bit(const unsigned long *addr1,
|
||||||
|
const unsigned long *addr2, unsigned long size,
|
||||||
|
unsigned long offset)
|
||||||
|
{
|
||||||
|
return _find_next_bit(addr1, addr2, size, offset, 0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hweightN - returns the hamming weight of a N-bit word
|
||||||
|
* @x: the word to weigh
|
||||||
|
*
|
||||||
|
* The Hamming Weight of a number is the total number of bits set in it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned int __sw_hweight32(unsigned int w)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_ARCH_HAS_FAST_MULTIPLIER
|
||||||
|
w -= (w >> 1) & 0x55555555;
|
||||||
|
w = (w & 0x33333333) + ((w >> 2) & 0x33333333);
|
||||||
|
w = (w + (w >> 4)) & 0x0f0f0f0f;
|
||||||
|
return (w * 0x01010101) >> 24;
|
||||||
|
#else
|
||||||
|
unsigned int res = w - ((w >> 1) & 0x55555555);
|
||||||
|
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
|
||||||
|
res = (res + (res >> 4)) & 0x0F0F0F0F;
|
||||||
|
res = res + (res >> 8);
|
||||||
|
return (res + (res >> 16)) & 0x000000FF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int __sw_hweight16(unsigned int w)
|
||||||
|
{
|
||||||
|
unsigned int res = w - ((w >> 1) & 0x5555);
|
||||||
|
res = (res & 0x3333) + ((res >> 2) & 0x3333);
|
||||||
|
res = (res + (res >> 4)) & 0x0F0F;
|
||||||
|
return (res + (res >> 8)) & 0x00FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int __sw_hweight8(unsigned int w)
|
||||||
|
{
|
||||||
|
unsigned int res = w - ((w >> 1) & 0x55);
|
||||||
|
res = (res & 0x33) + ((res >> 2) & 0x33);
|
||||||
|
return (res + (res >> 4)) & 0x0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long __sw_hweight64(uint64_t w)
|
||||||
|
{
|
||||||
|
#if BITS_PER_LONG == 32
|
||||||
|
return __sw_hweight32((unsigned int)(w >> 32)) +
|
||||||
|
__sw_hweight32((unsigned int)w);
|
||||||
|
#elif BITS_PER_LONG == 64
|
||||||
|
#ifdef CONFIG_ARCH_HAS_FAST_MULTIPLIER
|
||||||
|
w -= (w >> 1) & 0x5555555555555555ul;
|
||||||
|
w = (w & 0x3333333333333333ul) + ((w >> 2) & 0x3333333333333333ul);
|
||||||
|
w = (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0ful;
|
||||||
|
return (w * 0x0101010101010101ul) >> 56;
|
||||||
|
#else
|
||||||
|
uint64_t res = w - ((w >> 1) & 0x5555555555555555ul);
|
||||||
|
res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
|
||||||
|
res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
|
||||||
|
res = res + (res >> 8);
|
||||||
|
res = res + (res >> 16);
|
||||||
|
return (res + (res >> 32)) & 0x00000000000000FFul;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
180
smartdns.c
180
smartdns.c
@@ -1,132 +1,136 @@
|
|||||||
|
#include "fast_ping.h"
|
||||||
|
#include "hashtable.h"
|
||||||
|
#include "list.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "fast_ping.h"
|
|
||||||
#include "list.h"
|
|
||||||
#include "bitmap.h"
|
|
||||||
#include "hashtable.h"
|
|
||||||
|
|
||||||
void smartdns_ping_result(const char *host, int seqno, struct timeval *tv, void *userptr)
|
void smartdns_ping_result(const char *host, FAST_PING_RESULT result, int seqno, struct timeval *tv, void *userptr)
|
||||||
{
|
{
|
||||||
double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0;
|
if (result == PING_RESULT_RESPONSE) {
|
||||||
printf("%16s: seq=%d time=%.3f\n", host, seqno, rtt);
|
double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0;
|
||||||
|
printf("%16s: seq=%d time=%.3f\n", host, seqno, rtt);
|
||||||
|
} else if (result == PING_RESULT_TIMEOUT) {
|
||||||
|
printf("%16s: seq=%d timeout\n", host, seqno);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int smartdns_init()
|
int smartdns_init()
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = fast_ping_init();
|
ret = fast_ping_init();
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
fprintf(stderr, "start ping failed.\n");
|
fprintf(stderr, "start ping failed.\n");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
fast_ping_result_callback(smartdns_ping_result);
|
fast_ping_result_callback(smartdns_ping_result);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
errout:
|
errout:
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int smartdns_run()
|
int smartdns_run()
|
||||||
{
|
{
|
||||||
sleep(1);
|
fast_ping_start("192.168.1.1", 2000, 0);
|
||||||
fast_ping_start("192.168.1.1", 2000, 0);
|
fast_ping_start("192.168.1.35", 2000, 0);
|
||||||
fast_ping_start("192.168.1.35", 2000, 0);
|
fast_ping_start("14.215.177.38", 2000, 0);
|
||||||
fast_ping_start("14.215.177.38", 2000, 0);
|
fast_ping_start("113.96.161.87", 2000, 0);
|
||||||
fast_ping_start("113.96.161.87", 2000, 0);
|
fast_ping_start("::1", 2000, 0);
|
||||||
//fast_ping_start("::1", 2000, 0);
|
fast_ping_start("12.4.3.1", 1000, 0);
|
||||||
while (1) {
|
while (1) {
|
||||||
sleep(10);
|
sleep(10);
|
||||||
//fast_ping_stop("192.168.1.35");
|
//fast_ping_stop("192.168.1.35");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void smartdns_exit()
|
void smartdns_exit()
|
||||||
{
|
{
|
||||||
fast_ping_exit();
|
fast_ping_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct data {
|
struct data {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
int n;
|
int n;
|
||||||
};
|
};
|
||||||
|
|
||||||
void list_test()
|
void list_test()
|
||||||
{
|
{
|
||||||
struct list_head head ;
|
struct list_head head;
|
||||||
struct list_head *iter;
|
struct list_head *iter;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&head);
|
INIT_LIST_HEAD(&head);
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
struct data *h = malloc(sizeof(struct data));
|
struct data *h = malloc(sizeof(struct data));
|
||||||
h->n = i;
|
h->n = i;
|
||||||
list_add(&h->list, &head);
|
list_add(&h->list, &head);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each(iter, &head) {
|
list_for_each(iter, &head)
|
||||||
struct data *d= list_entry(iter, struct data, list);
|
{
|
||||||
|
struct data *d = list_entry(iter, struct data, list);
|
||||||
printf("%d\n", d->n);
|
printf("%d\n", d->n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct data_hash {
|
struct data_hash {
|
||||||
struct hlist_node node;
|
struct hlist_node node;
|
||||||
int n;
|
int n;
|
||||||
char str[32];
|
char str[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
int hash_test()
|
int hash_test()
|
||||||
{
|
{
|
||||||
DEFINE_HASHTABLE(ht, 7);
|
DEFINE_HASHTABLE(ht, 7);
|
||||||
struct data_hash *temp;
|
struct data_hash *temp;
|
||||||
struct data_hash *obj;
|
struct data_hash *obj;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int key;
|
||||||
int key;
|
|
||||||
|
|
||||||
for (i = 11; i < 17; i++) {
|
for (i = 11; i < 17; i++) {
|
||||||
temp = malloc(sizeof(struct data_hash));
|
temp = malloc(sizeof(struct data_hash));
|
||||||
temp->n = i * i;
|
temp->n = i * i;
|
||||||
hash_add(ht, &temp->node, temp->n);
|
hash_add(ht, &temp->node, temp->n);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 11; i < 17; i++) {
|
for (i = 11; i < 17; i++) {
|
||||||
key = i * i;
|
key = i * i;
|
||||||
hash_for_each_possible(ht, obj, node, key) {
|
hash_for_each_possible(ht, obj, node, key)
|
||||||
printf("value: %d\n", obj->n);
|
{
|
||||||
};
|
printf("value: %d\n", obj->n);
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hash_string_test()
|
int hash_string_test()
|
||||||
{
|
{
|
||||||
DEFINE_HASHTABLE(ht, 7);
|
DEFINE_HASHTABLE(ht, 7);
|
||||||
struct data_hash *temp;
|
struct data_hash *temp;
|
||||||
struct data_hash *obj;
|
struct data_hash *obj;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int key;
|
||||||
int key;
|
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
temp = malloc(sizeof(struct data_hash));
|
temp = malloc(sizeof(struct data_hash));
|
||||||
sprintf(temp->str, "%d", i);
|
sprintf(temp->str, "%d", i);
|
||||||
hash_add(ht, &temp->node, hash_string(temp->str));
|
hash_add(ht, &temp->node, hash_string(temp->str));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
char key_str[32];
|
char key_str[32];
|
||||||
sprintf(key_str, "%d", i);
|
sprintf(key_str, "%d", i);
|
||||||
key = hash_string(key_str);
|
key = hash_string(key_str);
|
||||||
hash_for_each_possible(ht, obj, node, key) {
|
hash_for_each_possible(ht, obj, node, key)
|
||||||
printf("i = %d value: %s\n", i, obj->str);
|
{
|
||||||
};
|
printf("i = %d value: %s\n", i, obj->str);
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -171,19 +175,19 @@ int rbtree_test()
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
atexit(smartdns_exit);
|
atexit(smartdns_exit);
|
||||||
|
|
||||||
ret = smartdns_init();
|
ret = smartdns_init();
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
fprintf(stderr, "init smartdns failed.\n");
|
fprintf(stderr, "init smartdns failed.\n");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
return smartdns_run();
|
return smartdns_run();
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user