kobject_map

/* * linux/drivers/base/map.c * * (C) Copyright Al Viro 2002,2003 * Released under GPL v2. * * NOTE: data structure needs to be changed. It works, but for large dev_t * it will be too slow. It is isolated, though, so these changes will be * local to that file. */#include #include #include #include #include #include struct kobj_map {struct probe {struct probe *next; //同一主設備號下各組均有自己的probe,用以形成鏈表dev_t dev; //本組設備號unsigned long range; //本組設備範圍struct module *owner; //本組所屬modulekobj_probe_t *get; //本組kobject probe 檢測函數?int (*lock)(dev_t, void *); //本組訪問的鎖?void *data; //數據,字符設備爲cdev} *probes[255];struct mutex *lock; //互斥鎖,字符設備爲cdevs_lock};int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, struct module *module, kobj_probe_t *probe, int (*lock)(dev_t, void *), void *data){unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;unsigned index = MAJOR(dev);unsigned i;struct probe *p;if (n > 255)n = 255;p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL);if (p == NULL)return -ENOMEM;for (i = 0; i < n; i++, p++) {p->owner = module;p->get = probe;p->lock = lock;p->dev = dev;p->range = range;p->data = data;}mutex_lock(domain->lock);for (i = 0, p -= n; i < n; i++, p++, index++) {struct probe **s = &domain->probes[index % 255];while (*s && (*s)->range < range)s = &(*s)->next;p->next = *s;*s = p;}mutex_unlock(domain->lock);return 0;}void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range){unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;unsigned index = MAJOR(dev);unsigned i;struct probe *found = NULL;if (n > 255)n = 255;mutex_lock(domain->lock);for (i = 0; i < n; i++, index++) {struct probe **s;for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {struct probe *p = *s;if (p->dev == dev && p->range == range) {*s = p->next;if (!found)found = p;break;}}}mutex_unlock(domain->lock);kfree(found);}struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index){struct kobject *kobj;struct probe *p;unsigned long best = ~0UL;retry:mutex_lock(domain->lock);for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {struct kobject *(*probe)(dev_t, int *, void *);struct module *owner;void *data;if (p->dev > dev || p->dev + p->range - 1 < dev)continue;if (p->range - 1 >= best)break;if (!try_module_get(p->owner))continue;owner = p->owner;data = p->data;probe = p->get;best = p->range - 1;*index = dev - p->dev;if (p->lock && p->lock(dev, data) < 0) {module_put(owner);continue;}mutex_unlock(domain->lock);kobj = probe(dev, index, data);/* Currently ->owner protects _only_ ->probe() itself. */module_put(owner);if (kobj)return kobj;goto retry;}mutex_unlock(domain->lock);return NULL;}struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock){struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);int i;if ((p == NULL) || (base == NULL)) {kfree(p);kfree(base);return NULL;}base->dev = 1;base->range = ~0;base->get = base_probe;for (i = 0; i < 255; i++)p->probes[i] = base;p->lock = lock;return p;}
發佈了8 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章