static void dump_guarded_heap_area(guarded_heap_area& area) { printf("guarded heap area: %p\n", &area); printf("next heap area: %p\n", area.next); printf("guarded heap: %p\n", area.heap); printf("area id: %" B_PRId32 "\n", area.area); printf("base: 0x%" B_PRIxADDR "\n", area.base); printf("size: %" B_PRIuSIZE "\n", area.size); printf("page count: %" B_PRIuSIZE "\n", area.page_count); printf("used pages: %" B_PRIuSIZE "\n", area.used_pages); printf("lock: %p\n", &area.lock); size_t freeCount = 0; void* item = list_get_next_item(&area.free_list, NULL); while (item != NULL) { freeCount++; if ((((guarded_heap_page*)item)->flags & GUARDED_HEAP_PAGE_FLAG_USED) != 0) { printf("free list broken, page %p not actually free\n", item); } item = list_get_next_item(&area.free_list, item); } printf("free_list: %p (%" B_PRIuSIZE " free)\n", &area.free_list, freeCount); freeCount = 0; size_t runLength = 0; size_t longestRun = 0; for (size_t i = 0; i <= area.page_count; i++) { guarded_heap_page& page = area.pages[i]; if (i == area.page_count || (page.flags & GUARDED_HEAP_PAGE_FLAG_USED) != 0) { freeCount += runLength; if (runLength > longestRun) longestRun = runLength; runLength = 0; continue; } runLength = 1; for (size_t j = 1; j < area.page_count - i; j++) { if ((area.pages[i + j].flags & GUARDED_HEAP_PAGE_FLAG_USED) != 0) break; runLength++; } i += runLength - 1; } printf("longest free run: %" B_PRIuSIZE " (%" B_PRIuSIZE " free)\n", longestRun, freeCount); printf("pages: %p\n", area.pages); }
static void* guarded_heap_area_allocate(guarded_heap_area& area, size_t pagesNeeded, size_t size, size_t alignment) { if (pagesNeeded > area.page_count - area.used_pages) return NULL; // We use the free list this way so that the page that has been free for // the longest time is allocated. This keeps immediate re-use (that may // hide bugs) to a minimum. guarded_heap_page* page = (guarded_heap_page*)list_get_next_item(&area.free_list, NULL); for (; page != NULL; page = (guarded_heap_page*)list_get_next_item(&area.free_list, page)) { if ((page->flags & GUARDED_HEAP_PAGE_FLAG_USED) != 0) continue; size_t pageIndex = page - area.pages; if (pageIndex > area.page_count - pagesNeeded) continue; // Candidate, check if we have enough pages going forward // (including the guard page). bool candidate = true; for (size_t j = 1; j < pagesNeeded; j++) { if ((area.pages[pageIndex + j].flags & GUARDED_HEAP_PAGE_FLAG_USED) != 0) { candidate = false; break; } } if (!candidate) continue; size_t offset = size & (B_PAGE_SIZE - 1); void* result = (void*)((area.base + pageIndex * B_PAGE_SIZE + (offset > 0 ? B_PAGE_SIZE - offset : 0)) & ~(alignment - 1)); guarded_heap_page_allocate(area, pageIndex, pagesNeeded, size, alignment, result); area.used_pages += pagesNeeded; guarded_heap_pages_allocated(*area.heap, pagesNeeded); return result; } return NULL; }
static int dump_images_list(int argc, char **argv) { struct image *image = NULL; Team *team; if (argc > 1) { team_id id = strtol(argv[1], NULL, 0); team = team_get_team_struct_locked(id); if (team == NULL) { kprintf("No team with ID %ld found\n", id); return 1; } } else team = thread_get_current_thread()->team; kprintf("Registered images of team %ld\n", team->id); kprintf(" ID text size data size name\n"); while ((image = (struct image*)list_get_next_item(&team->image_list, image)) != NULL) { image_info *info = &image->info; kprintf("%6ld %p %-7ld %p %-7ld %s\n", info->id, info->text, info->text_size, info->data, info->data_size, info->name); } return 0; }
status_t _get_next_image_info(team_id teamID, int32 *cookie, image_info *info, size_t size) { if (size > sizeof(image_info)) return B_BAD_VALUE; // get the team Team* team = Team::Get(teamID); if (team == NULL) return B_BAD_TEAM_ID; BReference<Team> teamReference(team, true); // iterate through the team's images MutexLocker imageLocker(sImageMutex); struct image* image = NULL; int32 count = 0; while ((image = (struct image*)list_get_next_item(&team->image_list, image)) != NULL) { if (count == *cookie) { memcpy(info, &image->info.basic_info, size); (*cookie)++; return B_OK; } count++; } return B_ENTRY_NOT_FOUND; }
static int dump_images_list(int argc, char **argv) { struct image *image = NULL; Team *team; if (argc > 1) { team_id id = strtol(argv[1], NULL, 0); team = team_get_team_struct_locked(id); if (team == NULL) { kprintf("No team with ID %" B_PRId32 " found\n", id); return 1; } } else team = thread_get_current_thread()->team; kprintf("Registered images of team %" B_PRId32 "\n", team->id); kprintf(" ID %-*s size %-*s size name\n", B_PRINTF_POINTER_WIDTH, "text", B_PRINTF_POINTER_WIDTH, "data"); while ((image = (struct image*)list_get_next_item(&team->image_list, image)) != NULL) { image_info *info = &image->info.basic_info; kprintf("%6" B_PRId32 " %p %-7" B_PRId32 " %p %-7" B_PRId32 " %s\n", info->id, info->text, info->text_size, info->data, info->data_size, info->name); } return 0; }
static status_t deliver_multicast(net_protocol_module_info* module, net_buffer* buffer, bool deliverToRaw) { if (module->deliver_data == NULL) return B_OK; MutexLocker _(sMulticastGroupsLock); status_t status = B_OK; if (buffer->interface_address != NULL) { status = deliver_multicast(module, buffer, deliverToRaw, buffer->interface_address->interface); } else { #if 0 // FIXME: multicast net_domain_private* domain = (net_domain_private*)sDomain; RecursiveLocker locker(domain->lock); net_interface* interface = NULL; while (true) { interface = (net_interface*)list_get_next_item( &domain->interfaces, interface); if (interface == NULL) break; status = deliver_multicast(module, buffer, deliverToRaw, interface); if (status < B_OK) break; } #endif } return status; }
snet_buffer* snb_fetch(struct list* l, uint16 size) { snet_buffer* item = NULL; snet_buffer* newitem = NULL; if (!list_is_empty(l)) while ((item = (snet_buffer*)list_get_next_item(l, item)) != NULL) { if (item->allocatedSize >= size) { // This one is for us break; } } newitem = snb_attempt_reuse(item, size); /* the resulting reused one is the same * as we fetched? => remove it from list */ if (item == newitem) { list_remove_item(l, item); } return newitem; }
status_t image_debug_lookup_user_symbol_address(Team *team, addr_t address, addr_t *_baseAddress, const char **_symbolName, const char **_imageName, bool *_exactMatch) { // TODO: Work together with ELF reader and runtime_loader. For regular user // images we have the symbol and string table addresses. struct image *image = NULL; while ((image = (struct image*)list_get_next_item(&team->image_list, image)) != NULL) { image_info *info = &image->info.basic_info; if ((address < (addr_t)info->text || address >= (addr_t)info->text + info->text_size) && (address < (addr_t)info->data || address >= (addr_t)info->data + info->data_size)) continue; // found image *_symbolName = NULL; *_imageName = info->name; *_baseAddress = (addr_t)info->text; *_exactMatch = false; return B_OK; } return B_ENTRY_NOT_FOUND; }
uint16 snb_packets(struct list* l) { uint16 count = 0; snet_buffer* item = NULL; while ((item = (snet_buffer*)list_get_next_item(l, item)) != NULL) count++; return count; }
/*! Called by the get_next_sem_info() macro. */ status_t _get_next_sem_info(team_id teamID, int32 *_cookie, struct sem_info *info, size_t size) { if (!sSemsActive) return B_NO_MORE_SEMS; if (_cookie == NULL || info == NULL || size != sizeof(sem_info)) return B_BAD_VALUE; if (teamID < 0) return B_BAD_TEAM_ID; Team* team = Team::Get(teamID); if (team == NULL) return B_BAD_TEAM_ID; BReference<Team> teamReference(team, true); InterruptsSpinLocker semListLocker(sSemsSpinlock); // TODO: find a way to iterate the list that is more reliable sem_entry* sem = (sem_entry*)list_get_first_item(&team->sem_list); int32 newIndex = *_cookie; int32 index = 0; bool found = false; while (!found) { // find the next entry to be returned while (sem != NULL && index < newIndex) { sem = (sem_entry*)list_get_next_item(&team->sem_list, sem); index++; } if (sem == NULL) return B_BAD_VALUE; GRAB_SEM_LOCK(*sem); if (sem->id != -1 && sem->u.used.owner == team->id) { // found one! fill_sem_info(sem, info, size); newIndex = index + 1; found = true; } else newIndex++; RELEASE_SEM_LOCK(*sem); } if (!found) return B_BAD_VALUE; *_cookie = newIndex; return B_OK; }
/*! Counts the registered images from the specified team. Interrupts must be enabled. */ int32 count_images(Team *team) { struct image *image = NULL; int32 count = 0; MutexLocker locker(sImageMutex); while ((image = (struct image*)list_get_next_item(&team->image_list, image)) != NULL) { count++; } return count; }
void snb_park(struct list* l, snet_buffer* snb) { snet_buffer* item = NULL; // insert it by order while ((item = (snet_buffer*)list_get_next_item(l, item)) != NULL) { // This one has allocated more than us place us back if (item->allocatedSize > snb->allocatedSize) { list_insert_item_before(l, item, snb); return; } } // no buffer bigger than us(or empty).. then at the end list_add_item(l, snb); }
ssize_t socket_count_connected(net_socket *_parent) { net_socket_private *parent = (net_socket_private *)_parent; MutexLocker _(parent->lock); ssize_t count = 0; void *item = NULL; while ((item = list_get_next_item(&parent->connected_children, item)) != NULL) { count++; } return count; }
static int dump_domains(int argc, char** argv) { DomainList::Iterator iterator = sDomains.GetIterator(); while (net_domain_private* domain = iterator.Next()) { kprintf("domain: %p, %s, %d\n", domain, domain->name, domain->family); kprintf(" module: %p\n", domain->module); kprintf(" address_module: %p\n", domain->address_module); if (!list_is_empty(&domain->interfaces)) kprintf(" interfaces:\n"); net_interface* interface = NULL; while (true) { interface = (net_interface*)list_get_next_item(&domain->interfaces, interface); if (interface == NULL) break; kprintf(" %p\n", interface); } if (!domain->routes.IsEmpty()) kprintf(" routes:\n"); RouteList::Iterator routeIterator = domain->routes.GetIterator(); while (net_route* route = routeIterator.Next()) { kprintf(" %p\n", route); } if (!domain->route_infos.IsEmpty()) kprintf(" route infos:\n"); RouteInfoList::Iterator infoIterator = domain->route_infos.GetIterator(); while (net_route_info* info = infoIterator.Next()) { kprintf(" %p\n", info); } } return 0; }
uint32 count_domain_interfaces() { MutexLocker locker(sDomainLock); uint32 count = 0; DomainList::Iterator iterator = sDomains.GetIterator(); while (net_domain_private* domain = iterator.Next()) { net_interface* interface = NULL; while (true) { interface = (net_interface*)list_get_next_item(&domain->interfaces, interface); if (interface == NULL) break; count++; } } return count; }
status_t copy_images(team_id fromTeamId, Team *toTeam) { // get the team Team* fromTeam = Team::Get(fromTeamId); if (fromTeam == NULL) return B_BAD_TEAM_ID; BReference<Team> teamReference(fromTeam, true); MutexLocker locker(sImageMutex); struct image *image = NULL; while ((image = (struct image*)list_get_next_item(&fromTeam->image_list, image)) != NULL) { image_id id = register_image(toTeam, &image->info, sizeof(image->info), true); if (id < 0) return id; } return B_OK; }
/*! Dumps a list of all interfaces into the supplied userland buffer. If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is returned. */ status_t list_domain_interfaces(void* _buffer, size_t* bufferSize) { MutexLocker locker(sDomainLock); UserBuffer buffer(_buffer, *bufferSize); DomainList::Iterator iterator = sDomains.GetIterator(); while (net_domain_private* domain = iterator.Next()) { RecursiveLocker locker(domain->lock); net_interface* interface = NULL; while (true) { interface = (net_interface*)list_get_next_item(&domain->interfaces, interface); if (interface == NULL) break; ifreq request; strlcpy(request.ifr_name, interface->name, IF_NAMESIZE); if (interface->address != NULL) { memcpy(&request.ifr_addr, interface->address, interface->address->sa_len); } else { // empty address request.ifr_addr.sa_len = 2; request.ifr_addr.sa_family = AF_UNSPEC; } if (buffer.Copy(&request, IF_NAMESIZE + request.ifr_addr.sa_len) == NULL) return buffer.Status(); } } *bufferSize = buffer.ConsumedAmount(); return B_OK; }
struct image* image_iterate_through_team_images(team_id teamID, image_iterator_callback callback, void* cookie) { // get the team Team* team = Team::Get(teamID); if (team == NULL) return NULL; BReference<Team> teamReference(team, true); // iterate through the team's images MutexLocker imageLocker(sImageMutex); struct image* image = NULL; while ((image = (struct image*)list_get_next_item(&team->image_list, image)) != NULL) { if (callback(image, cookie)) break; } return image; }
static int dump_driver(int argc, char** argv) { int i; snet_buffer* item = NULL; for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) { if (bt_usb_devices[i] != NULL) { kprintf("%s : \n", bt_usb_devices[i]->name); kprintf("\taclroom = %d\teventroom = %d\tcommand & events =%d\n", snb_packets(&bt_usb_devices[i]->eventRoom), snb_packets(&bt_usb_devices[i]->aclRoom), snb_packets(&bt_usb_devices[i]->snetBufferRecycleTrash)); while ((item = (snet_buffer*)list_get_next_item( &bt_usb_devices[i]->snetBufferRecycleTrash, item)) != NULL) snb_dump(item); } } return 0; }
static status_t callout_thread(void* /*data*/) { status_t status = B_OK; do { bigtime_t timeout = B_INFINITE_TIMEOUT; if (status == B_TIMED_OUT || status == B_OK) { // scan timers for new timeout and/or execute a timer mutex_lock(&sLock); struct callout* c = NULL; while (true) { c = (callout*)list_get_next_item(&sTimers, c); if (c == NULL) break; if (c->due < system_time()) { struct mtx *mutex = c->c_mtx; // execute timer list_remove_item(&sTimers, c); c->due = -1; sCurrentCallout = c; mutex_unlock(&sLock); if (mutex != NULL) mtx_lock(mutex); c->c_func(c->c_arg); if (mutex != NULL) mtx_unlock(mutex); mutex_lock(&sLock); sCurrentCallout = NULL; c = NULL; // restart scanning as we unlocked the list } else { // calculate new timeout if (c->due < timeout) timeout = c->due; } } sTimeout = timeout; mutex_unlock(&sLock); } status = acquire_sem_etc(sWaitSem, 1, B_ABSOLUTE_TIMEOUT, timeout); // the wait sem normally can't be acquired, so we // have to look at the status value the call returns: // // B_OK - a new timer has been added or canceled // B_TIMED_OUT - look for timers to be executed // B_BAD_SEM_ID - we are asked to quit } while (status != B_BAD_SEM_ID); return B_OK; }