/*-----------------------------------------------------------------------------------------------*\ \*-----------------------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*--- #include ---*/ #define AVM_EVENT_INTERNAL #include #include /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ extern spinlock_t avm_event_lock; static struct _avm_event_item *Items; static struct _avm_event_data *Datas; static unsigned int max_Items, max_Datas; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ struct _avm_event_queue { unsigned int rx, tx, size, count; void **data; }; struct _avm_event_queue free_Items; struct _avm_event_queue free_Datas; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avm_event_deinit2(void) { if(free_Items.data) { /*--- check if all Items are in free Queue ---*/ if(free_Items.count != (free_Items.size - 1)) { printk("[avm_event] ERROR: not all Item(s) freeed %u missing\n", (free_Items.size - 1) - free_Items.count); return 1; } } if(free_Datas.data) { /*--- check if all Datas are in free Queue ---*/ if(free_Datas.count != (free_Datas.size - 1)) { printk("[avm_event] ERROR: not all Data(s) freeed %u missing\n", (free_Datas.size - 1) - free_Datas.count); return 1; } } if(Items) kfree(Items); if(Datas) kfree(Datas); if(free_Items.data) kfree(free_Items.data); if(free_Datas.data) kfree(free_Datas.data); return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avm_event_init2(unsigned int max_items, unsigned int max_datas) { unsigned int i; Items = (struct _avm_event_item *)kmalloc(sizeof(struct _avm_event_item) * max_items, GFP_KERNEL); if(Items == NULL) { return -ENOMEM; } max_Items = max_items; free_Items.data = (void **)kmalloc(sizeof(void *) * (max_items + 1), GFP_KERNEL); if(free_Items.data == NULL) { kfree(Items); return -ENOMEM; } for(i = 0 ; i < max_items ; i++) { free_Items.data[i] = &Items[i]; } free_Items.rx = 0; free_Items.tx = max_items; free_Items.count = max_items; free_Items.size = max_items + 1; Datas = (struct _avm_event_data *)kmalloc(sizeof(struct _avm_event_data) * max_datas, GFP_KERNEL); if(Datas == NULL) { kfree(Items); kfree(free_Items.data); return -ENOMEM; } max_Datas = max_datas; free_Datas.data = (void **)kmalloc(sizeof(void *) * (max_datas + 1), GFP_KERNEL); if(free_Datas.data == NULL) { kfree(Items); kfree(Datas); kfree(free_Items.data); return -ENOMEM; } for(i = 0 ; i < max_datas ; i++) { free_Datas.data[i] = &Datas[i]; } free_Datas.rx = 0; free_Datas.tx = max_datas; free_Datas.count = max_datas; free_Datas.size = max_datas + 1; return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ struct _avm_event_data *avm_event_alloc_data(void) { struct _avm_event_data *D; unsigned long flags; spin_lock_irqsave(&avm_event_lock, flags); if(free_Datas.rx == free_Datas.tx) { spin_unlock_irqrestore(&avm_event_lock, flags); return NULL; } D = free_Datas.data[free_Datas.rx++]; if(free_Datas.rx >= free_Datas.size) free_Datas.rx = 0; free_Datas.count--; spin_unlock_irqrestore(&avm_event_lock, flags); return D; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_event_free_data(struct _avm_event_data *D) { unsigned long flags; spin_lock_irqsave(&avm_event_lock, flags); if(D->link_count) { D->link_count--; } if(D->link_count) { spin_unlock_irqrestore(&avm_event_lock, flags); return; } spin_unlock_irqrestore(&avm_event_lock, flags); kfree(D->data); spin_lock_irqsave(&avm_event_lock, flags); /*--- es sind auf jeden fall genügend elemente in der Queue ---*/ free_Datas.data[free_Datas.tx++] = D; if(free_Datas.tx >= free_Datas.size) free_Datas.tx = 0; free_Datas.count++; spin_unlock_irqrestore(&avm_event_lock, flags); return; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ struct _avm_event_item *avm_event_alloc_item(void) { struct _avm_event_item *I; unsigned long flags; spin_lock_irqsave(&avm_event_lock, flags); if(free_Items.rx == free_Items.tx) { spin_unlock_irqrestore(&avm_event_lock, flags); return NULL; } I = free_Items.data[free_Items.rx++]; if(free_Items.rx >= free_Items.size) free_Items.rx = 0; free_Items.count--; spin_unlock_irqrestore(&avm_event_lock, flags); return I; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_event_free_item(struct _avm_event_item *I) { unsigned long flags; if(I->data) { avm_event_free_data(I->data); } spin_lock_irqsave(&avm_event_lock, flags); /*--- es sind auf jeden fall genügend elemente in der Queue ---*/ free_Items.data[free_Items.tx++] = I; if(free_Items.tx >= free_Items.size) free_Items.tx = 0; free_Items.count++; spin_unlock_irqrestore(&avm_event_lock, flags); return; }