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

📄 sos_module_fetcher.c

📁 嵌入式操作系统内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C; tab-width:4 -*- *//* ex: set ts=4 shiftwidth=4 softtabstop=4 cindent: */#include <hardware.h>#include <codemem.h>#include <sos_module_fetcher.h>#include <sos_timer.h>#include <message.h>#include <sos_info.h>#include <malloc.h>#include <random.h>#include <led_dbg.h>#ifdef SOS_HAS_EXFLASH#include <exflash.h>#endif#ifdef SOS_SIM#include <sim_interface.h>#endif#include <led_dbg.h>#ifndef SOS_DEBUG_FETCHER#undef DEBUG#define DEBUG(...)#endif/** * @brief A reliable transport service for modules * * The protocol will fetch data from one hop communication (i.e. no routing) * base on given module version, ID, and size of module. * When the protocol fetch is complete, it will inform the requester * * We do not queue any request at this moment.  The reason is that * the probability of getting more than one request is rather low. * This means that the components that use fetcher will have to handle the * failure */static sos_module_t fetcher_module;static inline void handle_overheard_fragment(Message *msg);static int8_t handle_request(Message *msg);static int8_t handle_data(Message *msg);static void free_send_state_map(void);static int8_t fetcher_handler(void *state, Message *msg);static inline void handle_request_timeout(void);static inline void send_fragment(void);static inline void restart_request_timer(void);static void check_map_and_post(void);static void start_new_fetch(void);static void send_fetcher_done(void);static bool check_map(fetcher_bitmap_t *m);#ifndef SOS_DEBUG_FETCHER#define print_bitmap(m)#elsestatic void print_bitmap(fetcher_bitmap_t *m);#endifstatic const mod_header_t mod_header SOS_MODULE_HEADER ={  .mod_id = KER_FETCHER_PID,  .state_size = 0,  .num_timers = 1,  .num_sub_func = 0,  .num_prov_func = 0,  .module_handler = fetcher_handler,};//! the status of sending fragmentenum {    FETCHER_SENDING_FRAGMENT_INTERVAL  = 512L,};typedef struct {    uint16_t dest;    fetcher_fragment_t *fragr;  //!< the code fragment that will be stored    fetcher_fragment_t *frag;  //!< the code fragment that will be sent    fetcher_bitmap_t   *map;    sos_timer_t        timer;	uint8_t            num_funcs;} fetcher_sending_state_t;/** * @brief state for sending fragments * The reason we merge sending and receiving is because * we can send the fragment we have just received. */static fetcher_sending_state_t send_state;/** * @brief state for fetching fragments */static fetcher_state_t *fst = NULL;/** * @brief variable used for resending MSG_FETCHER_DONE * We use FETCHER_REQUEST_TID as retry timer */static bool no_mem_retry = false;int8_t fetcher_request(sos_pid_t req_id, sos_cam_t key, uint16_t size, uint16_t src){    uint8_t bitmap_size;   //! size of the bitmap in bytes    uint16_t num_fragments;    uint8_t i;    fetcher_state_t *f;	fetcher_cam_t *cam;		cam = (fetcher_cam_t *) ker_cam_lookup(key);	if( cam == NULL ) return -EINVAL;    //if(fst != NULL) return -EBUSY;    DEBUG_PID(KER_FETCHER_PID, "fetcher_request, req_id = %d, size = %d, src = %d\n", req_id, size, src);    num_fragments = ((size + (FETCHER_FRAGMENT_SIZE - 1))/ FETCHER_FRAGMENT_SIZE);    bitmap_size = (uint8_t)((num_fragments + 7)/ 8);    //DEBUG("size = %d\n", sizeof(fetcher_state_t) + bitmap_size);    f = ker_malloc(sizeof(fetcher_state_t) + bitmap_size, KER_FETCHER_PID);    if(f == NULL) {        return -ENOMEM;    }    //DEBUG("num_fragments = %d, bitmap_zie = %d\n", num_fragments, bitmap_size);    f->requester       = req_id;    f->map.key         = key;    f->map.bitmap_size = bitmap_size;    f->src_addr        = src;	f->num_funcs       = 0;    f->next            = NULL;	f->cm              = cam->cm;    for(i = 0; i < bitmap_size; i++) {        f->map.bitmap[i] = 0xff;    }    if((num_fragments) % 8) {        f->map.bitmap[bitmap_size - 1] =            (1 << (num_fragments % 8)) - 1;    }    print_bitmap(&f->map);    //! backoff first!!!    f->retx = 0;    if(fst != NULL) {        fetcher_state_t *tmp = fst;		cam->status = FETCHING_QUEUED;        while(tmp->next != NULL) { tmp = tmp->next; }        tmp->next = f;        return SOS_OK;    }	cam->status = FETCHING_STARTED;    fst = f;    //! setup timer    ker_timer_start(KER_FETCHER_PID,            FETCHER_REQUEST_TID,            FETCHER_REQUEST_BACKOFF_SLOT * ((ker_rand() % FETCHER_REQUEST_MAX_SLOT) + 1));    //DEBUG("request ret = %d\n", ret);    return SOS_OK;}int8_t fetcher_cancel(sos_pid_t req_id, sos_cam_t key){    fetcher_state_t *tmp;    fetcher_state_t *prev;    if( fst == NULL ) return -EINVAL;    if( fst->map.key == key ) {	        tmp = fst;        start_new_fetch();        ker_free( tmp );		/*		 * Cancel sender as well		 */		if( (send_state.map != NULL) && (send_state.map->key == key)) {			free_send_state_map();		}        return SOS_OK;    }    prev = fst;    tmp = fst->next;    while(tmp != NULL) {        if( tmp->map.key == key ) {	            prev->next = tmp->next;            ker_free( tmp );            return SOS_OK;	        }        prev = tmp;        tmp = tmp->next;    }    return -EINVAL;}void fetcher_restart(fetcher_state_t *s, uint16_t src){	fetcher_cam_t *cam;	cam = ker_cam_lookup( s->map.key );    s->src_addr = src;    s->retx = 0;	s->next = NULL;    if(fst != NULL) {        fetcher_state_t *tmp = fst;		cam->status = FETCHING_QUEUED;        while(tmp->next != NULL) { tmp = tmp->next; }        tmp->next = s;        return;    }    fst = s;	cam->status = FETCHING_STARTED;    ker_timer_start(KER_FETCHER_PID,            FETCHER_REQUEST_TID,            FETCHER_REQUEST_BACKOFF_SLOT * ((ker_rand() % FETCHER_REQUEST_MAX_SLOT) + 1));}void fetcher_commit(fetcher_state_t *s, bool commit){	fetcher_cam_t *cam;	cam = (fetcher_cam_t *) ker_cam_lookup(s->map.key);	if( cam == NULL ) return;	if( commit == true ) {		ker_codemem_flush( cam->cm, KER_FETCHER_PID );	} else {		ker_codemem_free( cam->cm );	}}static void free_send_state_map(){	ker_free(send_state.map);	send_state.map = NULL;	ker_timer_stop(KER_FETCHER_PID, FETCHER_TRANSMIT_TID);}static int8_t fetcher_handler(void *state, Message *msg){    switch (msg->type) {        case MSG_FETCHER_FRAGMENT:        {			fetcher_fragment_t *f;			f = (fetcher_fragment_t*)msg->data;			f->key = entohs( f->key );			f->frag_id = entohs(f->frag_id);			DEBUG_PID(KER_FETCHER_PID,"MSG_FETCHER_FRAGMENT:\n");			handle_overheard_fragment(msg);			if(fst == NULL) {				DEBUG_PID(KER_FETCHER_PID, "NO Request!!!\n");				return SOS_OK;  //!< no request			}			//DEBUG_PID(KER_FETCHER_PID,"calling restart_request_timer()\n");			restart_request_timer();			fst->retx = 0;			//DEBUG_PID(KER_FETCHER_PID,"calling handle_data()\n");			return handle_data(msg);		}		case MSG_FETCHER_REQUEST:		{			fetcher_bitmap_t *bmap =				(fetcher_bitmap_t *) msg->data;			bmap->key = entohs( bmap->key );			//! received request from neighbors			DEBUG("handling request to %d from %d\n", msg->daddr, msg->saddr);			if(msg->daddr == ker_id()) {				return handle_request(msg);			}			if(fst == NULL) return SOS_OK;  //!< no request			restart_request_timer();			fst->retx = 0;			return SOS_OK;		}		case MSG_TIMER_TIMEOUT:		{			MsgParam *params = (MsgParam*)(msg->data);			if(params->byte == FETCHER_REQUEST_TID) {				//DEBUG("request timeout\n");				if( no_mem_retry ) {					send_fetcher_done();					return SOS_OK;				}				handle_request_timeout();			} else if(params->byte == FETCHER_TRANSMIT_TID) {				//DEBUG("send fragment timeout\n");				send_fragment();			}			return SOS_OK;		}#ifdef SOS_HAS_EXFLASH		case MSG_EXFLASH_WRITEDONE:		{			ker_free(send_state.fragr);			send_state.fragr = NULL;			check_map_and_post();			return SOS_OK;		}		case MSG_EXFLASH_READDONE:		{			post_auto(KER_FETCHER_PID,					KER_FETCHER_PID,					MSG_FETCHER_FRAGMENT,					sizeof(fetcher_fragment_t),					send_state.frag,					SOS_MSG_RELEASE,					send_state.dest);			send_state.frag = NULL;			return SOS_OK;		}#endif		case MSG_INIT:		{			send_state.map = NULL;			send_state.frag = NULL;			send_state.fragr = NULL;			ker_msg_change_rules(KER_FETCHER_PID, SOS_MSG_RULES_PROMISCUOUS);			ker_permanent_timer_init(&(send_state.timer), KER_FETCHER_PID, FETCHER_TRANSMIT_TID, TIMER_REPEAT);			ker_timer_init(KER_FETCHER_PID, FETCHER_REQUEST_TID, TIMER_ONE_SHOT);			return SOS_OK;		}	}	return -EINVAL;}static inline void restart_request_timer(){	ker_timer_restart(KER_FETCHER_PID,			FETCHER_REQUEST_TID,			FETCHER_REQUEST_WATCHDOG + (FETCHER_REQUEST_BACKOFF_SLOT * ((ker_rand() % FETCHER_REQUEST_MAX_SLOT) + 1)));}static inline void handle_request_timeout(){	if(fst == NULL) {		return;	}	//sos_assert(fst != NULL);	//DEBUG("handle request timeout, retx = %d\n", fst->retx);	fst->retx++;	if(fst->retx <= FETCHER_REQUEST_MAX_RETX) {		fetcher_bitmap_t *m;		uint8_t size = sizeof(fetcher_bitmap_t) + fst->map.bitmap_size;		DEBUG_PID(KER_FETCHER_PID,"send request to %d\n", fst->src_addr);		print_bitmap(&fst->map);

⌨️ 快捷键说明

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