/* Iterates through a page and coalesces free buffers. Called only after freeing allocated space on the page. Checks a buffer with its buddy and coalesces the two if both are free. */ void coalesce(pageheaderT* page) { freelistL* buffer = get_required_buffer(1, page); allocheaderT* alloc; allocheaderT* prev = NULL; while (buffer != NULL) { alloc = buffer->first_block; while (alloc != NULL) { if (alloc->next != NULL && (get_buddy(alloc) == alloc->next)) { if (prev == NULL) buffer->first_block = alloc->next->next; else prev->next = alloc->next->next; page->used += 1; kma_free(alloc, alloc->size * 2); return; } else alloc = alloc->next; } buffer = buffer->bigger_size; } }
int is_free(uint64_t pd) { uint64_t buddy = get_buddy(pd, descr_table[pd].level); while(descr_table[buddy].level > descr_table[pd].level) { pd = buddy; } return (descr_table[pd].is_free == PAGE_DESCRIPTOR_AVAILABLE); // && (descr_table[buddy].level != descr_table[pd].level // || descr_table[buddy].is_free == PAGE_DESCRIPTOR_AVAILABLE)); }
void buddy_deallocate(phys_t addr, unsigned int lvl) { uint64_t pd = addr_to_pd(addr); insert_to_level(lvl, descr_table + pd); descr_table[pd].is_free = PAGE_DESCRIPTOR_AVAILABLE; for(unsigned int i = lvl; i < MAX_SIZE - 1; ++i) { uint64_t buddy = get_buddy(pd, i); if(buddy >= dt_size || !(descr_table[buddy].is_free == PAGE_DESCRIPTOR_AVAILABLE && descr_table[buddy].level == i)) { return; } merge(pd, buddy, i + 1); } }
// the user programmer should provide the correct level // correct === the current level is not empty, while the level below is void push_down(unsigned int level) { assert_true((heads[level].next != NULL), "push_down first contract"); assert_true((level > 0), "push_down second contract"); assert_true((heads[level - 1].next == NULL), "push_down third contract"); uint64_t pd_id = heads[level].next->pd_id; uint64_t buddy_id = get_buddy(pd_id, level - 1); page_descr* pd = descr_table + pd_id; page_descr* buddy = descr_table + buddy_id; extract_from_level(level, pd); // it is significant that previous level is empty heads[level - 1].next = pd; set_page_descr(pd, pd->pd_id, PAGE_DESCRIPTOR_AVAILABLE, level - 1, heads + (level - 1), buddy); set_page_descr(buddy, buddy->pd_id, PAGE_DESCRIPTOR_AVAILABLE, level - 1, pd, NULL); }
bool MatchPool::pop(int size_type, std::vector<MatchEntity*> &camps) { if (camps.size() != size_t(_camp_size)) { return false; } // find entity for first camp MatchEntity *ent = camps[0]; if (!top(*ent, size_type)) { return false; } // find others' camp members with size_type for (size_t i = 1;i < camps.size(); i++) { MatchEntity *opp = camps[i]; if (!get_opponent(ent, opp, ent->size)) { return false; } } // find left members int size = ent->get_size(); while (size < _team_size) { // find buddies if (!get_buddy(_team_size - size, camps[0])) { return false; } // find oppoents for (size_t i = 1;i < camps.size(); i++) { if (!get_opponent(camps[0], camps[i], _team_size - size)) { return false; } } size += camps[0]->get_size(); } return true; }
void shee(void *ptr) { /* Nothing to do */ if (ptr == NULL) { return; } // LOG("BEFORE SHEE AVAIL MAP\n"); // LOG("Mem_pool size = 2^%luB\n", mp.pool_size); // print_avail_map(); struct block *b = B_HEAD(ptr); struct block *buddy = NULL; b->state = FREE; // LOG("Going to free:\n"); //LOG("Shee block of size 2^%luB = %luB\n", b->k_size, pow2(b->k_size)); // print_block_info(b); /* Combine free block if buddy-possible */ unsigned long k_size = b->k_size; while (k_size < mp.pool_size) { /* Find my buddy */ buddy = get_buddy(b, k_size); /* Is buddy available? */ if (buddy->state == USED) { break; } /* Is buddy used somewhere inside? */ if (buddy->k_size != k_size) { break; } /* Combine buddies together */ buddy->prev->next = buddy->next; buddy->next->prev = buddy->prev; k_size++; if (buddy < b) { b = buddy; } } /* Put block on proper 'avail' list */ b->state = FREE; b->k_size = k_size; struct block *p; p = mp.avail[b->k_size].next; b->next = p; p->prev = b; b->prev = (struct block *) &mp.avail[b->k_size]; mp.avail[b->k_size].next = b; // LOG("AFTER SHEE AVAIL MAP\n"); // print_avail_map(); // LOG("\n"); //TODO: Bude provadet jine vlakno - vyresi se problem uklizeni poolu // po neuspesnem shallocu, ktery byl proveden jako prvni /* Shrink down memory pool if possible */ int enableDestroy = 1; while (enableDestroy && !list_empty(&mp.avail[mp.pool_size-1])) { b = mp.avail[mp.pool_size-1].next; buddy = get_buddy(b, mp.pool_size-1); /* Is 'b' free block on the top of the heap with half of the pool size? */ if (b < buddy) { break; } /* Correct the 'avail' array of old pool */ mp.avail[mp.pool_size].prev = (struct block *) &mp.avail[mp.pool_size]; mp.avail[mp.pool_size].next = (struct block *) &mp.avail[mp.pool_size]; LOG("--## SHRINKING ##--\n"); /* Then we can shrink the heap/pool */ if (sbrk(-pow2(b->k_size)) == (void *) -1) { perror("sbrk"); } mp.pool_size--; LOG("Pool size is now %lu\n", mp.pool_size); /* Correct the 'avail' array */ mp.avail[mp.pool_size].prev = (struct block *) &mp.avail[mp.pool_size]; mp.avail[mp.pool_size].next = (struct block *) &mp.avail[mp.pool_size]; /* If only the first block with 'avail' array is on heap, we can clean-up */ if (mp.pool_size == mp.init_size) { LOG("--## POOL DESTROYED ##--\n"); if (brk(mp.base_addr) == -1) { perror("brk"); } mp.base_addr = NULL; break; } } }
/* add user: ymsgr:addfriend?ID send message: ymsgr:sendim?ID&m=MESSAGE add chatroom: ymsgr:chat?ROOM */ static INT_PTR ServiceParseYmsgrLink(WPARAM wParam, LPARAM lParam) { TCHAR *arg = (TCHAR*)lParam; if (arg == NULL) return 1; /* sanity check */ /* skip leading prefix */ arg = _tcschr(arg, ':'); if (arg == NULL) return 1; /* parse failed */ for (++arg; *arg == '/'; ++arg) {} if (g_instances.getCount() == 0) return 0; CYahooProto *proto = g_instances[0]; for (int i = 0; i < g_instances.getCount(); ++i) { if (g_instances[i]->m_iStatus > ID_STATUS_OFFLINE) { proto = g_instances[i]; break; } } if (!proto) return 1; /* add a contact to the list */ if (!_tcsnicmp(arg, _T("addfriend?"), 10)) { arg += 10; char *id = get_buddy(&arg); if (!id) return 1; if (proto->getbuddyH(id) == NULL) /* does not yet check if id is current user */ { ADDCONTACTSTRUCT acs = {0}; PROTOSEARCHRESULT psr = {0}; acs.handleType = HANDLE_SEARCHRESULT; acs.szProto = proto->m_szModuleName; acs.psr = &psr; psr.cbSize = sizeof(PROTOSEARCHRESULT); psr.id = (TCHAR*)id; CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs); } mir_free(id); return 0; } /* send a message to a contact */ else if (!_tcsnicmp(arg, _T("sendim?"), 7)) { arg += 7; char *id = get_buddy(&arg); if (!id) return 1; TCHAR *msg = NULL; while (arg) { if (!_tcsnicmp(arg, _T("m="), 2)) { msg = arg + 2; url_decode(msg); break; } arg = _tcschr(arg + 1, '&'); /* first token */ if (arg) *arg = 0; } MCONTACT hContact = proto->add_buddy(id, id, 0, PALF_TEMPORARY); /* ensure contact is on list */ if (hContact) CallService(MS_MSG_SENDMESSAGET, hContact, (LPARAM)msg); mir_free(id); return 0; } /* open a chatroom */ else if (!_tcsnicmp(arg, _T("chat?"), 5)) { arg += 5; // char *id = get_buddy(&arg); // if (!id) return 1; /* not yet implemented (rm contains name of chatroom)*/ return 0; } return 1; /* parse failed */ }
errorcode helper_fsm_buddy_alloc(connlist_t *list, connlist_item_t *item) { /* declare variables */ connlist_item_t *found_buddy = NULL; comm_msg_buddy_alloc_t msg; errorcode ret; /* error check arguments */ CHECK_NOT_NULL(list,ERROR_NULL_ARG_1); CHECK_NOT_NULL(item,ERROR_NULL_ARG_2); /* do function */ ret = SUCCESS; /* receive the waiting message */ CHECK_FAILED(readMsg(item->info.socks.peer, COMM_MSG_WAITING_FOR_BUDDY_ALLOC,NULL,0),ERROR_NETWORK_READ); DEBUG(DBG_PROTOCOL,"PROTOCOL:received WAITING_FOR_BUDDY_ALLOC\n"); /* get pointer to buddy's info*/ if (FAILED(get_buddy(list,item,&found_buddy))){ DEBUG(DBG_BUDDY,"BUDDY:couldn't find buddy\n"); return ERROR_1; } DEBUG(DBG_BUDDY,"BUDDY:found buddy\n"); /* check to make sure all buddy's info has been filled in, * then fill in the message */ if (FAILED(wait_for_buddy_port_alloc(&(found_buddy->info)))){ ret = ERROR_1; goto forget_and_return; } msg.buddy_port_alloc = found_buddy->info.port_alloc.method; if ( (found_buddy->info.port_alloc.method == COMM_PORT_ALLOC_RAND) && (item->info.port_alloc.method == COMM_PORT_ALLOC_RAND) ) msg.support = COMM_CONNECTION_UNSUPPORTED; else msg.support = COMM_CONNECTION_SUPPORTED; /* send out message*/ if (FAILED(sendMsg(item->info.socks.peer,COMM_MSG_BUDDY_ALLOC, &msg,sizeof(comm_msg_buddy_alloc_t)))) { ret = ERROR_NETWORK_SEND; DEBUG(DBG_PROTOCOL, "fsm_buddy_alloc:PROTOCOL:sent BUDDY_ALLOC\n"); goto forget_and_return; } if (msg.support == COMM_CONNECTION_UNSUPPORTED) { DEBUG(DBG_VERBOSE, "VERBOSE:connection unsupported!\n"); ret = ERROR_2; goto forget_and_return; } /* enter next state */ if (FAILED(helper_fsm_buddy_port(list,item,found_buddy))) { ret = ERROR_CALLED_FUNCTION; goto forget_and_return; } forget_and_return: /* forget the buddy's info */ DEBUG(DBG_LIST, "LIST:forgeting about buddy entry\n"); CHECK_FAILED(connlist_forget(list,connlist_item_match,found_buddy), ERROR_3); return ret; }