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

📄 usched.c

📁 wimax BS simulation code,implemented under linux.
💻 C
字号:
/* * This piece of code is totally free. If any pitfalls found,  * please feel free to contact me at jetmotor@21cn.com * THANKS A LOT! */#include <stdio.h>#include <time.h>#include <stdlib.h>#include <string.h>#include <netinet/in.h>#include <semaphore.h>#include "task.h"#include "bitops.h"#include "wxbuff.h"#include "wxsched.h"typedef struct cdmaallocieinfo_tag{	struct list_head link;	uint8_t frame_number_index;//the least four bits of the frame number	uint8_t ranging_code;	uint8_t ranging_symbol;	uint8_t ranging_subchannel;	uint8_t is_bwr;}cdmaallocieinfo_t;schedque_t g_ulschedque;int32_t g_ulremain;	///3 symbols per slot in uplink 					/* unit in slot */int32_t g_ulmapsize;static int32_t ulbandwidth_alloc(sfattr_t *sf);static void build_ulmap(wxbuff_t *map);static void do_watchdog(uint32_t arga, void *argb);int32_t usched_init(){	int32_t i;		memset(&g_ulschedque, 0, sizeof(schedque_t));	pthread_mutex_init(&g_ulschedque.mutex, NULL);	g_ulschedque.watchdog = get_timer(WXTIMER_TRIGGER, 40, 0, NULL, do_watchdog);	g_ulschedque.map = get_wxbuff(NULL);	for ( i = 0; i < MAX_PRIORITY; i++ ) {		INIT_LIST_HEAD(&g_ulschedque.array[0].queue[i]);//active		INIT_LIST_HEAD(&g_ulschedque.array[1].queue[i]);//expired	}	g_ulschedque.active = &g_ulschedque.array[0];	g_ulschedque.expired = &g_ulschedque.array[1];	INIT_LIST_HEAD(&g_ulschedque.scheded_ss);	INIT_LIST_HEAD(&g_ulschedque.mapie);		return 0;}void * do_task_ulsched(void *arg){	uint32_t prio;	sfattr_t *sf;	for ( ; ; ) {//nr_ulsymbol = 18;channel =30		g_ulremain = g_bsinfo.nr_ulsymbol * g_bsinfo.channel_nr / UL_SYMBOLS_PER_SLOT -  12 - 18;//#define UL_SYMBOLS_PER_SLOT	3		///10 = 6+4 6:genmachdr ; 4:crc		g_ulmapsize = 30 * BYTES_PER_SLOT_QPSK_12 - 10 - sizeof(ulmaphdr_t) - sizeof(cdmarngie_t) - sizeof(cdmabwrie_sh4_t) + 1;		sem_wait(&sem_usched);		start_timer(g_ulschedque.watchdog);		init_wxbuff(g_ulschedque.map);		pthread_mutex_lock(&g_ulschedque.mutex);		while ( g_ulmapsize > sizeof(ulmapie_t) ) {/*只要当前剩下的ulmap长度大于ulmapie,就继续调度*/						if ( test_and_clear_bit(SCHED_WATCHDOG_TIMEOUT, (volatile unsigned long *)&g_ulschedque.signal) )				break;			if ( g_ulschedque.active->nr_active == 0 ) {/*如果当前active 个数为零,那么就把expired 赋值给active													*并继续进行调度*/				prio_array_t *temp;								temp = g_ulschedque.active;				g_ulschedque.active = g_ulschedque.expired;				g_ulschedque.expired = temp;				continue;			}			prio = find_first_bit((const unsigned long *)g_ulschedque.active->bitmap, MAX_PRIORITY);                        sf = list_entry(g_ulschedque.active->queue[prio].next, sfattr_t, ulink);                        list_del(g_ulschedque.active->queue[prio].next);                        if ( list_empty(&g_ulschedque.active->queue[prio]) )                                clear_bit(prio, (volatile unsigned long *)g_ulschedque.active->bitmap);                        g_ulschedque.active->nr_active--;			pthread_mutex_lock(&sf->mutex);                        if ( ulbandwidth_alloc(sf) < 0 ) break;/*0:have no bandwidth to allocate  -1:bandwidth insufficent*/			prio = trytobe_fair(sf);/*重新计算服务流的优先级并把它插入到上行调度expired优先级队列中*/                        list_add_tail(&sf->ulink, &g_ulschedque.expired->queue[prio]);                        pthread_mutex_unlock(&sf->mutex);                        set_bit(prio, (volatile unsigned long *)g_ulschedque.expired->bitmap);                        g_ulschedque.expired->nr_active++;/*expired 队列里存放的是已经调度过的并且重新计算过优先级的服务流*/		}                cancel_timer(g_ulschedque.watchdog);                clear_bit(SCHED_WATCHDOG_TIMEOUT, (volatile unsigned long *)&g_ulschedque.signal);                build_ulmap(g_ulschedque.map);		set_bit(SCHED_MAP_STANDBY, (volatile unsigned long *)&g_ulschedque.signal);                pthread_mutex_unlock(&g_ulschedque.mutex);	}	return NULL;}/*该函数重新编辑了服务流的优先级*/int32_t trytobe_fair(sfattr_t *sf){	int32_t prio;	prio =  (sf->priority + sf->policy) >> 1;	if ( sf->service_flow_scheduling_type == UPLINK_GRANT_SCHEDULING_TYPE_UGS 	     || sf->service_flow_scheduling_type == UPLINK_GRANT_SCHEDULING_TYPE_ERTPS ) {		uint32_t distance;				if ( g_bsinfo.frame < sf->last )			distance = g_bsinfo.frame + 0xffffff - sf->last;		else 			distance = g_bsinfo.frame - sf->last;		prio += (sf->sdu_inter_arrival_interval << 1) / FRAME_LENGTH - distance - 16;	}	else {		uint32_t min;				/* overflow preventing */		min = ((uint32_t)sf->_bwr < (uint32_t)sf->_data) ? sf->_bwr : sf->_data;		sf->_bwr -= min;		sf->_data -= min;		prio += (sf->_bwr - sf->_data) >> 7;	}	if ( prio < 0 ) prio = 0;	else if ( prio >= MAX_PRIORITY ) prio = MAX_PRIORITY - 1;	sf->priority = prio;			return prio;}/* return:	0, no bandwidth will be allocated for this service flow. *		>0, bandwidth allocated. *		-1, bandwidth resource is insufficient. */ /*带宽分配的单位是时隙该函数把   分配好的带宽放到ssinfo中去,然 后 再把这个ss插入上行调度队列中* 而带宽分配是基于sf的,为什么?*/static int32_t ulbandwidth_alloc(sfattr_t *sf){	uint32_t bwg, slots, distance, bytes, least, elapse;	uint32_t type, min, max, grant, policy, interval, ss;		if ( sf->stat == SF_INVALID )		return 0;	type	= sf->service_flow_scheduling_type;	min	= sf->minimum_reserved_traffic_rate;	max	= sf->maximum_sustained_traffic_rate;	grant	= sf->unsolicited_grant_interval;	policy	= sf->request_transmission_policy;	interval= sf->sdu_inter_arrival_interval;	ss	= sf->ss;//bwg:unit of bytes	if ( g_bsinfo.frame < sf->last )//reder:g_bsinfo.frame ?sf->last :the frame number of the last scheded occurs		distance = g_bsinfo.frame + 0xffffff - sf->last;///24 bits	else 		distance = g_bsinfo.frame - sf->last;//distance means the distance between the bs current number and the number of the sf when  the last scheded occurs	/* do bandwidth calculation specific to scheduling types */	elapse = distance * FRAME_LENGTH;//FRAME_LENGTH =5ms,elapse means the elapse time after the last scheded occurs 	if ( type == UPLINK_GRANT_SCHEDULING_TYPE_UGS ) {				if ( elapse >= grant ) {//grant = grant interval			if ( sf->fixed_variable_length_indicator == FIXED_LENGTH_SDU )				bwg = ((elapse * sf->sdu_size) >> 1) / interval;//why divided by interval ? unit of interval ?			else				bwg = (elapse * min) >> 13;//right moving means divided;  13 = 10 + 3  :2^13 = 2^10 * 2^3		}		else			return 0;	}	else if ( type == UPLINK_GRANT_SCHEDULING_TYPE_ERTPS ) {		if ( elapse >= grant )			bwg = (elapse * min) >> 13;		else			return 0;	}	else if ( sf->bwr == 0 )		return 0;	else {		bwg = (elapse * (min + max)) >> 14;		if ( sf->bwr < bwg )			bwg = sf->bwr;	}		least = policy & NO_CRC ? 10 : 6;//least:means the least bytes ss needs,if no crc,then least equal 6,else 10	bytes = bytes_perslot(g_ssinfo[ss].uiuc, 1);	/* map bytes into slots */	if ( bwg > least ) {		slots = (bwg + bytes - 1) / bytes;		if ( slots < g_ulremain ) {/*上行仍有足够的时隙可供分配*/			g_ulremain -= slots;			g_ssinfo[ss].bwg += slots;/*分配的单位是时隙*/			sf->last = g_bsinfo.frame;			sf->bwr = 0;/*带宽请求在sf 中,带宽保证放在SS中*/			if ( list_empty(&g_ssinfo[ss].uscheded_link) ) {				list_add_tail(&g_ssinfo[ss].uscheded_link, &g_ulschedque.scheded_ss);/*为什么这样做,把调度过的ss放在队列中,而不是sf*/				g_ulschedque.nr_ss++;				g_ulmapsize -= sizeof(ulmapie_t);/*调度之后产生一个ulmapie,使得可用的ulmap长度减小*/			}			return 1;		}		else if ( g_ulremain * bytes > least ) {	/* g_ulremain <= slots */			g_ulremain = 0;			g_ssinfo[ss].bwg += g_ulremain;			sf->last = g_bsinfo.frame;			sf->bwr = 0;			if ( list_empty(&g_ssinfo[ss].uscheded_link) ) {				list_add_tail(&g_ssinfo[ss].uscheded_link, &g_ulschedque.scheded_ss);				g_ulschedque.nr_ss++;				g_ulmapsize -= sizeof(ulmapie_t);			}			return -1;		}		else			return 0;	}	else		return 0;}static void build_ulmap(wxbuff_t *map){	int8_t sh = 0;	genmachdr_t *machdr;	ulmaphdr_t *hdr;	struct list_head *pos, *tmp;/*初始化的时候map->end = map->beg,随着数据的填入,map->end 再不断增加*/	hdr = (ulmaphdr_t *)map->end;	hdr->hdr.msgtype = UL_MAP;	hdr->ucd_count = g_bsinfo.bp_active->count[1];	hdr->allocation_start_time = htonl(g_bsinfo.allocation_start_time);	hdr->no_ofdma_symbols = g_bsinfo.nr_ulsymbol;///18 symbols	map->end += sizeof(ulmaphdr_t);	/* cdma_ranging_ie	 * cdma_bandwidth_request_ie	 * normal_ie	 * cdma_allocation_ie	 */	{		cdmarngie_t cdmarngie;		cdmabwrie_sh4_t cdmabwrie_sh4;		memset(&cdmarngie, 0, sizeof(cdmarngie_t));		cdmarngie_set(&cdmarngie,			      0,			      12,			      0,			      0,			      2,			      6,			      0,			      0);		memcpy(map->end,  &cdmarngie, sizeof(cdmarngie_t));		map->end += sizeof(cdmarngie_t);				memset(&cdmabwrie_sh4, 0, sizeof(cdmabwrie_sh4_t));		cdmabwrie_sh4_set(&cdmabwrie_sh4,				  map->end,				  0,				  12,				  2,				  0,				  3,				  6,				  2,				  0);		map->end--;		memcpy(map->end, &cdmabwrie_sh4, sizeof(cdmabwrie_sh4_t));		map->end += sizeof(cdmabwrie_sh4_t);	}/*上行调度器把分配好的带宽放在ssinfo中,然后再把该ss 放到scheded_ss中*//*这里根据分配给SS的带宽形成ulmap消息*/	list_for_each_safe(pos, tmp, &g_ulschedque.scheded_ss) {//list_for_each_safe is a for( ; ; )		ssinfo_t *ss;		ulmapie_t ie;				list_del_init(pos);		ss = list_entry(pos, ssinfo_t, uscheded_link);				pthread_mutex_lock(&ss->mutex);		if ( ss->stat == SS_INVALID )			continue;		memset(&ie, 0, sizeof(ulmapie_t));		ulmapie_set(&ie,			    ss->sf[0]->cid,/*basic CID*/			    ss->uiuc,			    ss->bwg,			    0);		memcpy(map->end, &ie, sizeof(ulmapie_t));		map->end += sizeof(ulmapie_t);				/* make clean ASAP */		ss->bwg = 0;#if 0		for ( i = 0; i < ss->nr_sf; i++ )			sf->bwr = 0;#endif		pthread_mutex_unlock(&ss->mutex);	}	list_for_each_safe(pos, tmp, &g_ulschedque.mapie) {		cdmaallocieinfo_t *cdmaallocieinfo;		if ( g_ulmapsize < sizeof(cdmaallocie_t) || g_ulremain < 20 )			break;		list_del(pos);		cdmaallocieinfo = list_entry(pos, cdmaallocieinfo_t, link);				if ( sh == 0 ) {			cdmaallocie_t cdmaallocie;			memset(&cdmaallocie, 0, sizeof(cdmaallocie_t));			cdmaallocie_set(&cdmaallocie, 					0,			/* cid */					12,			/* uiuc */					20,			/* duration */					0,			/* uiuc_for_transmission */					0,			/* repetition_coding_indication */					cdmaallocieinfo->frame_number_index, 					cdmaallocieinfo->ranging_code, 					cdmaallocieinfo->ranging_symbol, 					cdmaallocieinfo->ranging_subchannel, 					cdmaallocieinfo->is_bwr);			memcpy(map->end, &cdmaallocie, sizeof(cdmaallocie_t));			map->end += sizeof(cdmaallocie_t);			g_ulmapsize -= sizeof(cdmaallocie_t);		}		else {			cdmaallocie_sh4_t cdmaallocie_sh4;						memset(&cdmaallocie_sh4, 0, sizeof(cdmaallocie_sh4_t));			cdmaallocie_sh4_set(&cdmaallocie_sh4,					    map->end,					    0,					    12,					    20,					    0,					    0,					    cdmaallocieinfo->frame_number_index, 					    cdmaallocieinfo->ranging_code, 					    cdmaallocieinfo->ranging_symbol, 					    cdmaallocieinfo->ranging_subchannel, 					    cdmaallocieinfo->is_bwr);			map->end--;			memcpy(map->end, &cdmaallocie_sh4, sizeof(cdmaallocie_sh4_t));			map->end += sizeof(cdmaallocie_t);			g_ulmapsize -= (sizeof(cdmaallocie_sh4_t) - 1);		}				g_ulremain -= 20;		sh = !sh;		free(cdmaallocieinfo);	}	memset(map->end, 0, 4);///4 bytes used as crc	map->end += 4;	map->beg -= sizeof(genmachdr_t);/*ulmap消息需要一个通用的mac 头*/	map->tolen = map->len = map->end - map->beg;	machdr = (genmachdr_t *)map->beg;	genmachdr_set(machdr, 0, 0, 0, 0, 1, 0, map->tolen, 0xffff);	/* may apply padding bits */	return;}static void do_watchdog(uint32_t arga, void *argb){	time_t tm;	time(&tm);	fprintf(stdout, "usched do_watchdog @ jiffies:%d, %s", jiffies, ctime(&tm));	set_bit(SCHED_WATCHDOG_TIMEOUT, (volatile unsigned long *)&g_ulschedque.signal);	return;}int32_t post_cdmaie(cdmacode_t *cdmacode){	cdmaallocieinfo_t *cdmaallocieinfo;	if ( (cdmaallocieinfo = (cdmaallocieinfo_t *)malloc(sizeof(cdmaallocieinfo_t))) != NULL ) {		cdmaallocieinfo->frame_number_index = cdmacode->frame_number_index;		cdmaallocieinfo->ranging_code = cdmacode->ranging_code;		cdmaallocieinfo->ranging_symbol = cdmacode->ranging_symbol;		cdmaallocieinfo->ranging_subchannel = cdmacode->ranging_subchannel;		cdmaallocieinfo->is_bwr = cdmacode->is_bwr;		list_add_tail(&g_ulschedque.mapie, &cdmaallocieinfo->link);	}	return 0;}

⌨️ 快捷键说明

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