#include "sys_config.h" #include "tx_platform.h" #include "list.h" #include "typesdef.h" #include "osal/string.h" #include "stream_frame.h" #include "utlist.h" #include "osal/work.h" #include "basic_include.h" static int unbind_stream(stream *s); typedef void *(*stream_malloc)(int size); typedef void (*stream_free)(void *ptr); stream *g_s = NULL; stream *d_s = NULL; uint8_t stream_not_gc = 0; static void *extern_malloc(int size) { return os_malloc(size); } static void extern_free(void *ptr) { if (ptr) { os_free(ptr); } } stream_malloc self_malloc = extern_malloc; stream_free self_free = extern_free; static int default_free_data_func(struct data_structure *d) { int res = 0; uint32_t flags; int ref; flags = disable_irq(); ref = --d->ref; enable_irq(flags); if(ref < 0) { os_printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); } //释放空间 if(ref == 0) { //先调用注册的删除函数,后通知流 if(d->ops && d->ops->free) { d->ops->free(d); } res = d->s->func(d->s,d,STREAM_DATA_FREE); //返回0,代表不需要删除data,如果返回>0,代表data实体已经无效 if(res > 0) { d->data = NULL; } flags = disable_irq(); DL_DELETE(d->s->src_d_list_u,d); d->prev = NULL; d->next = NULL; DL_APPEND(d->s->src_d_list_f, d); enable_irq(flags); d->s->func(d->s,d,STREAM_DATA_FREE_END); } return 0; } static int default_stream_priv_func(stream *s,void *priv,int opcode) { return 0; } static void *creat_stream(const char *name) { stream *s = (stream*)self_malloc(sizeof(stream)); if(!s) { goto creat_stream_end; } memset(s,0,sizeof(stream)); s->name = name; s->ref = 0; //代表有人创建了,所以一定是有人在使用 s->used = STREAM_AVAILABLE; s->d_list_f = NULL; s->d_list_u = NULL; s->ref++; //往链表头插入,保护 DL_PREPEND(g_s, s); creat_stream_end: return s; } //查找是否存在对应的流名称 static void *find_stream(const char *name) { stream *s = NULL; stream *ret_s = NULL; uint32_t flags; //保护轮询,并且这个阶段不能进行gc stream *each_s = g_s; flags = disable_irq(); stream_not_gc = 1; DL_FOREACH(each_s,s) { if(!strcmp(s->name,name)) { s->open_ref++; s->ref++; ret_s = s; goto find_stream_end; } } find_stream_end: //轮询完毕,可以进行gc操作(gc的时候要全局保护,先对链表进行移动,最后单独进行回收) stream_not_gc = 0; enable_irq(flags); return ret_s; } //开放的接口 //对流的data空间进行分配,暂定buf是连续的,后续可以增加buf不连续的接口(避免申请一大片的空间) void stream_data_mem_dis(stream *s,uint8_t *buf_head,int uint_len,int count) { struct data_structure *elt; DL_FOREACH(s->src_d_list_f,elt) { if(count == 0) { break; } elt->data = buf_head; buf_head += uint_len; count--; } } //对data进行分配空间,用回调函数操作,count是分配的最大值 void stream_data_dis_mem(stream *s,int count) { struct data_structure *elt; int data_count = 0; DL_FOREACH(s->src_d_list_f,elt) { if(count == 0) { break; } elt->priv = (void*)data_count++; s->func(s,elt,STREAM_DATA_DIS); count--; } } //对data进行分配空间(自定义),用回调函数操作 void stream_data_dis_mem_custom(stream *s) { struct data_structure *elt; int data_count = 0; DL_FOREACH(s->src_d_list_f,elt) { elt->priv = (void*)data_count++; s->func(s,elt,STREAM_DATA_DIS); } } //强行引用加1,特殊作用,适合一次性占用多次,并且不需要经过find_stream的流程,前提流是可用的 int open_stream_again(stream *s) { uint32_t flags; int res = 0; flags = disable_irq(); if(s->used == STREAM_ISUED) { s->open_ref++; s->ref++; } else { res = 1; } enable_irq(flags); return 0; } //打开一个可用的流,如果没有,则创建一个,如果已经存在,则使用原来的,则参数除了name,其他无效 void *open_stream_available(const char *name,int data_count,int recv_count,stream_priv_func func,void *priv) { uint32_t flags; stream *s = NULL; //检查是否已经创建过了 s = find_stream(name); if(s) { //判断一下状态,如果是在使用,则代表被创建过,直接返回 if(s->used == STREAM_ISUED) { goto open_stream_available_end; } else { flags = disable_irq(); s->open_ref--; s->ref--; enable_irq(flags); } } s = (stream *)open_stream(name,data_count,recv_count,func,priv); open_stream_available_end: return s; } //打开对应的流,如果需要生产data,则data_count>0,如果只是接收,recv_count>0,根据需求来填写 void *open_stream(const char *name,int data_count,int recv_count,stream_priv_func func,void *priv) { stream *s = NULL; void *src_d_list_head = NULL; void *d_list_head = NULL; uint32_t flags; if(func) { func(NULL,priv,STREAM_OPEN_ENTER); } //先申请对应的空间 if(data_count > 0) { src_d_list_head = (void*)self_malloc(data_count*sizeof(struct data_structure)); if(src_d_list_head) { memset(src_d_list_head,0,data_count*sizeof(struct data_structure)); } } if(recv_count > 0) { d_list_head = (void*)self_malloc(recv_count*sizeof(struct data_list)); if(d_list_head) { memset(d_list_head,0,recv_count*sizeof(struct data_list)); } } if((data_count>0 && !src_d_list_head) || (recv_count > 0 && !d_list_head)) { if(src_d_list_head) { self_free(src_d_list_head); } if(d_list_head) { self_free(d_list_head); } src_d_list_head = NULL; d_list_head = NULL; goto open_stream_end; } //检查是否已经创建过了 s = find_stream(name); if(s) { //stream不是可用或者不是重复可用,则返回空,代表名称有了,可能没有及时回收,需要等待及时回收才可以创建同一个名字的流 if(s->used != STREAM_AVAILABLE_AGAIN && s->used != STREAM_AVAILABLE) { flags = disable_irq(); s->open_ref--; s->ref--; enable_irq(flags); s = NULL; goto open_stream_end; } flags = disable_irq(); //没有被使用,则初始化对应数据 s->used = STREAM_ISUED; enable_irq(flags); } //没有找到对应的流,则创建 else { //这是第一次创建,不需要锁 s = creat_stream(name); if(s) { s->open_ref++; s->used = STREAM_ISUED; } } //创建对应data_list_f数量,相当于初始化 struct data_structure *tmp_data_s = (struct data_structure *)src_d_list_head; for(int i=0;isrc_d_list_f, tmp_data_s); tmp_data_s->free = default_free_data_func; tmp_data_s->s = s; tmp_data_s++; } struct data_list *tmp_data_list = (struct data_list *)d_list_head; for(int i=0;id_list_f, tmp_data_list); tmp_data_list++; } open_stream_end: if(s) { s->src_d_list_count = data_count; s->src_d_list_head = src_d_list_head; s->d_list_head = d_list_head; if(func) { s->func = func; func(s,priv,STREAM_OPEN_EXIT); } else { s->func = default_stream_priv_func; } } else { //如果没有流,看看是否申请了空间 if(src_d_list_head) { self_free(src_d_list_head); } if(d_list_head) { self_free(src_d_list_head); } if(func) { func(s,priv,STREAM_OPEN_FAIL); } } return s; } int close_stream(stream *s) { if(!s) { return 1; } uint32_t flags; uint32_t ref; flags = disable_irq(); ref = --s->open_ref; enable_irq(flags); //如果流还有被打开过,则需要等待另一个占用被释放 if(ref) { flags = disable_irq(); s->ref--; //理论这里不可能等于0 enable_irq(flags); return 2; } struct data_list *elt,*tmp; s->enable = 0; //关闭使能 s->used = STREAM_UNAVAILABLE; //代表不可使用 s->func(s,NULL,STREAM_CLOSE_ENTER); //释放一下自己接收到的数据链表内容,然后它就没有接收的数据了 DL_FOREACH_SAFE(s->d_list_u,elt,tmp) { //从已有链表释放 DL_DELETE(s->d_list_u,elt); //进行elt->data删除 free_data(elt->data); //放回到空闲链表 elt->prev = NULL; elt->next = NULL; flags = disable_irq(); DL_APPEND(s->d_list_f,elt); enable_irq(flags); } s->func(s,NULL,STREAM_CLOSE_EXIT); s->ref--; s->used = STREAM_WAIT_GC_MARKER; //等待gc标记处理 //统计src_d_list_f是否与count一致(如果不一致,可能存在悬空态,但未实际发送到流,正常不应该出现这个情况),实际是判断src_d_list_u是否还有被使用,如果有,代表还不能释放 //剩下交给gc去处理而不是在这里处理 #if 0 //还有人在引用或者data的数据还在被使用,则不能删除 if(s->ref || s->src_d_list_u) { //不能被删除,则由gc去定时去检查处理,一直等到处理完成才进行删除操作 } else { //释放链表 if(s->src_d_list_head) { self_free(s->src_d_list_head); } if(s->d_list_head) { self_free(s->d_list_head); } //used设置为0,则可以重新创建,因为对应的空间已经被删除完毕 s->used = 0; //最后可以等到gc自己去删除,而不是主动删除,gc删除可能会延时一段时间,为了统一删除而不会怕有太多异步的可能性 } #endif return 0; } //内部使用解锁绑定 static int unbind_stream(stream *s) { if(!s) { return 1; } uint32_t flags; os_printf("%s name:%s\tref:%d\n",__FUNCTION__,s->name,s->ref); flags = disable_irq(); s->ref--; //理论这里不可能等于0 enable_irq(flags); return 0; } //s为数据产生的源头,然后绑定对应的name int streamSrc_bind_streamDest(stream *s,const char *name) { int res = -1; stream *dest = NULL; struct stream_list *s_list; dest = find_stream(name); if(dest) { //保证是可用的 if(dest->used >= 0) { s_list = (struct stream_list *)self_malloc(sizeof(struct stream_list)); if(s_list) { memset(s_list,0,sizeof(struct stream_list)); s_list->s = dest; DL_APPEND(s->s_list, s_list); res = 0; } else { dest->ref--; } } else { dest->ref--; } dest->open_ref--; } //如果name不存在,则创建一个空的stream s else { dest = creat_stream(name); if(dest) { s_list = (struct stream_list *)self_malloc(sizeof(struct stream_list)); if(s_list) { memset(s_list,0,sizeof(struct stream_list)); s_list->s = dest; DL_APPEND(s->s_list, s_list); res = 0; } } } return res; } //解绑定 int streamSrc_unbind_streamDest(stream *s,const char *name) { int res = -1; struct stream_list *elt,*tmp; stream *dest = NULL; dest = find_stream(name); if(dest) { DL_FOREACH_SAFE(s->s_list,elt,tmp) { if(dest == elt->s) { DL_DELETE(s->s_list,elt); dest->ref--; self_free(elt); res = 0; break; } } uint32_t flags; flags = disable_irq(); //find_stream的时候ref增加了,所以要-- dest->ref--; dest->open_ref--; enable_irq(flags); } else { } return res; } //向stream中发送data数据,会轮询s_list链表发送 int send_data_to_stream(struct data_structure *data) { struct stream_list *elt; struct data_list *d_list,*tmp; int count = 0; //计算发送到多少个数据流 uint32_t flags; data->ref++; flags = disable_irq(); //放到已经使用的链表中 DL_APPEND(data->s->src_d_list_u, data); enable_irq(flags); data->s->func(data->s,data,STREAM_SEND_DATA_START); DL_FOREACH(data->s->s_list,elt) { if(elt->s->enable && elt->s->used == STREAM_ISUED) { //先判断一下该数据是否要发送到流,如果不需要,则不需要进行往下操作 if(elt->s->func(elt->s,data,STREAM_FILTER_DATA)) { continue; } d_list = NULL; //获取elt->s中可以使用的数据链表,如果没有则不发送过去,代表对方空间不够 flags = disable_irq(); DL_FOREACH_SAFE(elt->s->d_list_f,d_list,tmp) { DL_DELETE(elt->s->d_list_f,d_list); break; } enable_irq(flags); if(d_list) { data->s->func(data->s,data,STREAM_SEND_TO_DEST); count++; data->ref++; d_list->data = data; //链表的next与prev清空 d_list->next = NULL; d_list->prev = NULL; //发送到可用的链表 flags = disable_irq(); DL_APPEND(elt->s->d_list_u, d_list); enable_irq(flags); //调用对应唤醒的接口 elt->s->func(elt->s,data,STREAM_RECV_DATA_FINISH); } } } //告诉流,发送数据完成 data->s->func(data->s,data,STREAM_SEND_DATA_FINISH); //进行删除,应该是调用回调函数 if(data->free) { data->free(data); } return count; } //强行进行data删除,可能已经不再需要 int force_del_data(struct data_structure *data) { if(!data) { return 0; } uint32_t flags; data->ref++; //放到已经使用的链表中 flags = disable_irq(); DL_APPEND(data->s->src_d_list_u, data); enable_irq(flags); //进行删除,应该是调用回调函数 if(data->free) { data->free(data); } return 0; } //获取data的空间链表,用于生成数据 struct data_structure *get_src_data_f(stream *s) { struct data_structure *data,*tmp; uint32_t flags; data = NULL; DL_FOREACH_SAFE(s->src_d_list_f,data,tmp) { flags = disable_irq(); DL_DELETE(s->src_d_list_f,data); enable_irq(flags); data->prev = NULL; data->next = NULL; data->type = 0; break; } return data; } //接收data的链表,用于从其他流接收到数据 struct data_structure *recv_real_data(stream *s) { if(!s) { return NULL; } uint32_t flags; struct data_list *data,*tmp; struct data_structure *real_data = NULL; data = NULL; DL_FOREACH_SAFE(s->d_list_u,data,tmp) { //从used中移除 flags = disable_irq(); DL_DELETE(s->d_list_u,data); enable_irq(flags); data->prev = NULL; data->next = NULL; if(!s->func(s,data->data,STREAM_RECV_FILTER_DATA)) { break; } //代表该数据包需要被过滤 else { flags = disable_irq(); DL_APPEND(s->d_list_f, data); enable_irq(flags); //删除对应的data free_data(data->data); data = NULL; } } if(data) { real_data = data->data; //放回到d_list_f flags = disable_irq(); DL_APPEND(s->d_list_f, data); enable_irq(flags); } return real_data; } int free_data(void *data_struct) { struct data_structure *data = (struct data_structure*)data_struct; if(data && data->free) { return data->free(data); } return 0; } //使能stream int enable_stream(stream *s,int enable) { if(!s) { return 1; } s->enable = enable; return 0; } //如果有注册获取get_data函数,则由get_data去获取,否则直接返回data->data的指针 void *get_stream_real_data(struct data_structure* data) { if(data && data->ops && data->ops->get_data) { return data->ops->get_data(data); } else { return data->data; } } uint32_t get_stream_real_data_len(struct data_structure* data) { if(data && data->ops && data->ops->get_data_len) { return data->ops->get_data_len(data); } else { return 0; } } uint32_t get_stream_data_timestamp(struct data_structure* data) { if(data && data->ops && data->ops->get_data_time) { return data->ops->get_data_time(data); } else { return data->timestamp; } } uint32_t set_stream_real_data_len(struct data_structure* data,uint32_t len) { if(data && data->ops && data->ops->set_data_len) { return data->ops->set_data_len(data,len); } else { return 0; } } uint32_t set_stream_data_time(struct data_structure* data,uint32_t timestamp) { if(data && data->ops && data->ops->set_data_time) { return data->ops->set_data_time(data,timestamp); } else { data->timestamp = timestamp; //默认 return 0; } } uint32_t stream_data_custom_cmd_func(struct data_structure* data,int opcode,void *priv) { if(data && data->ops && data->ops->custom_func) { return data->ops->custom_func(data,opcode,priv); } else { return 0; } } uint32_t register_stream_self_cmd_func(stream *s,stream_self_cmd func) { s->self_cmd_func = func; return 0; } uint32_t stream_self_cmd_func(stream *s,int opcode,uint32_t arg) { if(s && s->self_cmd_func) { return s->self_cmd_func(s,opcode,arg); } //没有对应的函数 return 1; } void broadcast_cmd_to_destStream(stream *s,uint32_t cmd) { struct stream_list *elt; DL_FOREACH(s->s_list,elt) { if(elt->s->enable && elt->s->used == STREAM_ISUED) { elt->s->func(elt->s,(void*)cmd,STREAM_SEND_CMD); } } } int stream_gc_marker_timer(uint32_t t) { stream *s; stream *each_s = g_s; //对链表进行轮询,检查是否要删除,如果需要删除,则进行标记,在另一个workqueue进行回收,与这个是同一个线程(这样不用考虑一些) DL_FOREACH(each_s,s) { if(s->used == STREAM_WAIT_GC_CLEAN) { continue; } //如果被标记或者ref为0,则会自动启动gc处理 if(s->used == STREAM_WAIT_GC_MARKER || s->ref == 0) { //删除自己bind的stream if(s->s_list) { struct stream_list *elt,*tmp; DL_FOREACH_SAFE(s->s_list,elt,tmp) { DL_DELETE(s->s_list,elt); //close_stream(elt->s); unbind_stream(elt->s); //elt->s->ref--; self_free(elt); } s->s_list = NULL; } //要删除,但是看一下对应的资源是否释放完成 //统计src_d_list_f是否与count一致(如果不一致,可能存在悬空态, //但未实际发送到流,正常不应该出现这个情况),实际是判断src_d_list_u是否还有被使用,如果有,代表还不能释放 if(!s->src_d_list_u) { //轮询src_d_list_f,查看是否有需要释放空间的可能 struct data_structure *data_tmp; DL_FOREACH(s->src_d_list_f,data_tmp) { s->func(s,data_tmp,STREAM_DATA_DESTORY); } //可以进行资源释放 if(s->src_d_list_head) { self_free(s->src_d_list_head); s->src_d_list_head = NULL; } if(s->d_list_head) { self_free(s->d_list_head); s->d_list_head = NULL; } s->src_d_list_f = NULL; s->src_d_list_u = NULL; s->d_list_f = NULL; s->d_list_u = NULL; //状态修改 //代表资源相关资源被释放过,后续可以重复利用 s->used = STREAM_AVAILABLE_AGAIN; //如果引用为0,则代表这个流不需要继续存在,可以被删除 if(!s->ref) { s->used = STREAM_WAIT_GC_CLEAN; //交给下一个阶段的gc进行链表移位,删除 //如果这里将name设置为NULL,则可以在被清除之前也可以创建数据,但是有一个问题就是,尽量不要用类似全局,因为可能会推迟释放资源 os_printf("%s wait gc name:%s\t%X\n",__FUNCTION__,s->name,s); s->name = NULL; } } } } return t; } //返回下一次回收的时间,如果没有回收成功,则会10ms后重新进行回收 int stream_gc_clean_timer(uint32_t t) { static uint32_t gc_timer = 100; //不能进行回收,等待下一个轮回 if(stream_not_gc) { gc_timer = 10; goto stream_gc_clean_timer_end; } uint32_t flags; stream *el,*tmp; //可以进行回收,要进行全局保护 flags = disable_irq(); DL_FOREACH_SAFE(g_s,el,tmp) { //只是进行链表移位,最后才进行实际删除 if(el->used == STREAM_WAIT_GC_CLEAN) { DL_DELETE(g_s,el); el->next = NULL; el->prev = NULL; DL_PREPEND(d_s, el); } } enable_irq(flags); //链表进行回收 DL_FOREACH_SAFE(d_s,el,tmp) { //name已经被清除,在marker阶段被设置为NULL,所以name暂时不要用申请的空间,用静态(在flash) DL_DELETE(d_s,el); //进行资源的全部回收 //回调删除命令 if(el->func) { el->func(el,NULL,STREAM_DEL); } self_free(el); } gc_timer = t; stream_gc_clean_timer_end: return gc_timer; } static struct os_work gc_marker; static struct os_work gc_clean; static int32 stream_gc_marker_timer_work(struct os_work *work) { uint32_t t; t = stream_gc_marker_timer(5); os_run_work_delay(&gc_marker, t); return 0; } static int32 stream_gc_clean_timer_work(struct os_work *work) { uint32_t t; t = stream_gc_clean_timer(5); os_run_work_delay(&gc_clean, t); return 0; } void stream_work_queue_start() { OS_WORK_INIT(&gc_marker, stream_gc_marker_timer_work, 0); os_run_work_delay(&gc_marker, 1000); OS_WORK_INIT(&gc_clean, stream_gc_clean_timer_work, 0); os_run_work_delay(&gc_clean, 1000); }