📄 dsched.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 <string.h>#include "task.h"#include "que.h"#include "mac.h"#include "bitops.h"#include "wxbuff.h"#include "wxsched.h"schedque_t g_dlschedque;typedef struct bandwidth_s{ uint32_t off_symbol; uint32_t nr_symbol; uint32_t off_subchannel; uint32_t nr_subchannel;}bandwidth_t;bandwidth_t g_dlresource;uint32_t g_dlmapsize;static void do_watchdog(uint32_t arga, void *argb);static int32_t dlbandwidth_alloc(sfattr_t *sf, uint8_t *sh);static int32_t resource_arb(uint32_t *req, uint32_t *offsym, uint32_t *nrsym, uint32_t *offschn, uint32_t *nrschn);static wxbuff_t * build_burst_no_pack_frag(uint16_t cid, uint8_t ci, uint32_t grant);static wxbuff_t * build_burst_no_frag(uint16_t cid, uint8_t ci, uint8_t ext, uint32_t grant);static wxbuff_t * build_burst(uint16_t cid, uint8_t ci, uint8_t ext, uint32_t grant);int32_t dsched_init(){ int32_t i; memset(&g_dlschedque, 0, sizeof(schedque_t)); pthread_mutex_init(&g_dlschedque.mutex, NULL); g_dlschedque.watchdog = get_timer(WXTIMER_TRIGGER, 40, 0, NULL, do_watchdog); g_dlschedque.map = get_wxbuff(NULL); for ( i = 0; i < MAX_PRIORITY; i++ ) { INIT_LIST_HEAD(&g_dlschedque.array[0].queue[i]); INIT_LIST_HEAD(&g_dlschedque.array[1].queue[i]); } g_dlschedque.active = &g_dlschedque.array[0]; g_dlschedque.expired = &g_dlschedque.array[1]; INIT_LIST_HEAD(&g_dlschedque.scheded_ss); INIT_LIST_HEAD(&g_dlschedque.mapie); //sf_active(0); sf_active(0xffff); return 0;}extern void transmit_dcd(uint32_t arga, void *argb);extern void transmit_ucd(uint32_t arga, void *argb);void * do_task_dlsched(void *arg){ dlmaphdr_t *dlmaphdr; uint32_t prio; sfattr_t *sf; uint8_t sh; for ( ; ; ) { g_dlresource.off_symbol = 0; g_dlresource.nr_symbol = g_bsinfo.nr_dlsymbol;///28 g_dlresource.off_subchannel = 0; g_dlresource.nr_subchannel = g_bsinfo.channel_nr;///30 g_dlmapsize = g_bsinfo.channel_nr * BYTES_PER_SLOT_QPSK_12 - 10 - sizeof(dlmaphdr_t); //transmit_dcd(0, NULL); //transmit_ucd(0, NULL); sem_wait(&sem_dsched); start_timer(g_dlschedque.watchdog); sh = 0; init_wxbuff(g_dlschedque.map); dlmaphdr = (dlmaphdr_t *)g_dlschedque.map->beg; dlmaphdr->hdr.msgtype = DL_MAP; dlmaphdr->frame_duration_code = g_bsinfo.frame_duration_code; dlmaphdr->frame_number[0] = (g_bsinfo.frame & 0xff0000) >> 16; dlmaphdr->frame_number[1] = (g_bsinfo.frame & 0xff00) >> 8; dlmaphdr->frame_number[2] = g_bsinfo.frame & 0xff; dlmaphdr->dcd_count = g_bsinfo.bp_active->count[0]; memcpy(dlmaphdr->bsid, g_bsinfo.mac_addr, 6); g_dlschedque.map->end += sizeof(dlmaphdr_t); pthread_mutex_lock(&g_dlschedque.mutex); while ( g_dlmapsize > sizeof(dlmapie_1cid_t) ) { if ( test_and_clear_bit(SCHED_WATCHDOG_TIMEOUT, (volatile unsigned long *)&g_dlschedque.signal) ) break; if ( g_dlschedque.active->nr_active == 0 ) { prio_array_t *temp; temp = g_dlschedque.active; g_dlschedque.active = g_dlschedque.expired; g_dlschedque.expired = temp; continue; } prio = find_first_bit((const unsigned long *)g_dlschedque.active->bitmap, MAX_PRIORITY); sf = list_entry(g_dlschedque.active->queue[prio].next, sfattr_t, dlink); list_del(g_dlschedque.active->queue[prio].next); if ( list_empty(&g_dlschedque.active->queue[prio]) ) clear_bit(prio, (volatile unsigned long *)g_dlschedque.active->bitmap); g_dlschedque.active->nr_active--; pthread_mutex_lock(&sf->mutex); if ( dlbandwidth_alloc(sf, &sh) < 0 ) break; //prio = trytobe_fair(sf); list_add_tail(&sf->dlink, &g_dlschedque.expired->queue[prio]); pthread_mutex_unlock(&sf->mutex); set_bit(prio, (volatile unsigned long *)g_dlschedque.expired->bitmap); g_dlschedque.expired->nr_active++; } cancel_timer(g_dlschedque.watchdog); clear_bit(SCHED_WATCHDOG_TIMEOUT, (volatile unsigned long *)&g_dlschedque.signal); memset(g_dlschedque.map->end, 0, 4); g_dlschedque.map->end += 4; g_dlschedque.map->beg -= sizeof(genmachdr_t); g_dlschedque.map->mac = (genmachdr_t *)g_dlschedque.map->beg; g_dlschedque.map->tolen = g_dlschedque.map->len = g_dlschedque.map->end - g_dlschedque.map->beg; genmachdr_set(g_dlschedque.map->mac, 0, 0, 0, 0, 1, 0, g_dlschedque.map->tolen, 0xffff); set_bit(SCHED_MAP_STANDBY, (volatile unsigned long *)&g_dlschedque.signal); pthread_mutex_unlock(&g_dlschedque.mutex); } return NULL;}static int32_t dlbandwidth_alloc(sfattr_t *sf, uint8_t *sh){ uint32_t type, min, max, grant, policy, interval, distance; uint32_t req, offsym, nrsym, offschn, nrschn, ret; uint8_t diuc = g_ssinfo[sf->ss].diuc; uint8_t ci = !(policy & NO_CRC);;//crc indication wxbuff_t *wxb; if ( sf->stat == SF_INVALID ) return 0; /*softque 似乎是存放了所有来自有线网络的数据, * 缓存在这个数组中,size就是这块数据的长度*/ if ( ! (req = g_softque[sf->cid].size) ) 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; if ( g_bsinfo.frame < sf->last ) distance = g_bsinfo.frame + 0xffffff - sf->last; else distance = g_bsinfo.frame - sf->last; req = req / bytes_perslot(diuc, 0);//bytes to slots ret = resource_arb(&req, &offsym, &nrsym, &offschn, &nrschn); req = req * bytes_perslot(diuc, 0); if ( *sh == 0 ) { dlmapie_1cid_t *ie; ie = (dlmapie_1cid_t *)g_dlschedque.map->end; dlmapie_1cid_set(ie, diuc, sf->cid, offsym, offschn, 0, nrsym, nrschn, 0); g_dlschedque.map->end += sizeof(dlmapie_1cid_t); } else { dlmapie_1cid_sh4_t *ie; g_dlschedque.map->end--; ie = (dlmapie_1cid_sh4_t *)g_dlschedque.map->end; dlmapie_1cid_sh4_set(ie, ie, diuc, sf->cid, offsym, offschn, 0, nrsym, nrschn, 0); g_dlschedque.map->end += sizeof(dlmapie_1cid_sh4_t); } *sh = !*sh; g_dlmapsize -= sizeof(dlmapie_1cid_t); if ( policy & NO_PACK_FRAGMENT ) { wxb = build_burst_no_pack_frag(sf->cid, ci, req); } else if ( policy & NO_FRAGMENT ) { wxb = build_burst_no_frag(sf->cid, ci, sf->fsn_size, req); } else { wxb = build_burst(sf->cid, ci, sf->fsn_size, req); } if ( wxb ) ringq_enque_simple(&tq_bst_tx, &wxb->senior); /* else pack padding mac header or padding bits */ return ret;}static int32_t resource_arb(uint32_t *req, uint32_t *offsym, uint32_t *nrsym, uint32_t *offschn, uint32_t *nrschn){ uint32_t quotient_sym, quotient_schn, remainder_sym, remainder_schn;//商及余数 uint32_t total = g_dlresource.nr_symbol * g_dlresource.nr_subchannel; uint32_t total_1, total_2; *offsym = g_dlresource.off_symbol; *offschn = g_dlresource.off_subchannel; if ( total <= *req ) { *req = total; *nrsym = g_dlresource.nr_symbol; *nrschn = g_dlresource.nr_subchannel; return -1; } quotient_sym = *req / g_dlresource.nr_symbol; quotient_schn = *req / g_dlresource.nr_subchannel; remainder_sym = *req % g_dlresource.nr_symbol; remainder_schn = *req % g_dlresource.nr_subchannel; if ( remainder_schn == 0 ) { *nrsym = quotient_schn; *nrschn = g_dlresource.nr_subchannel; g_dlresource.nr_symbol -= quotient_schn; g_dlresource.off_symbol += quotient_schn; return 0; } if ( remainder_sym == 0 ) { *nrsym = g_dlresource.nr_symbol; *nrschn = quotient_sym; g_dlresource.nr_subchannel -= quotient_sym; g_dlresource.off_subchannel += quotient_sym; return 0; } total_1 = (++quotient_sym) * g_dlresource.nr_symbol; total_2 = (++quotient_schn) * g_dlresource.nr_subchannel; if ( total_2 <= total_1 ) { *nrsym = quotient_schn; *nrschn = g_dlresource.nr_subchannel; if ( total_2 == total ) return -1; g_dlresource.nr_symbol -= quotient_schn; g_dlresource.off_symbol += quotient_schn; } else { *nrsym = g_dlresource.nr_symbol; *nrschn = quotient_sym; if ( total_1 == total ) return -1; g_dlresource.nr_subchannel -= quotient_sym; g_dlresource.off_subchannel += quotient_sym; } return 0;}static wxbuff_t * build_burst_no_pack_frag(uint16_t cid, uint8_t ci, uint32_t grant){ struct list_head burst; wxbuff_t *wxb; uint32_t prefix, tolen = 0; INIT_LIST_HEAD(&burst); prefix = ci ? 10 : 6;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -