/*---------------------------------------------------------------------- | TestHashMap +---------------------------------------------------------------------*/ static int TestHashMap() { NPT_HashMap<NPT_String,A> a_map; A* a = NULL; CHECK(a_map.GetEntryCount() == 0); CHECK(a_map.HasKey("hello") == false); CHECK(!a_map.HasValue(A(1,2))); CHECK(NPT_FAILED(a_map.Get("bla", a))); CHECK(a == NULL); a_map.Put("hello", A(1,2)); CHECK(a_map.GetEntryCount() == 1); CHECK(NPT_SUCCEEDED(a_map.Get("hello", a))); CHECK(*a == A(1,2)); CHECK(a_map.HasKey("hello")); CHECK(a_map.HasValue(A(1,2))); CHECK(a_map["hello"] == A(1,2)); CHECK(a_map["bla"] == A()); CHECK(a_map.GetEntryCount() == 2); a_map["bla"] = A(3,4); CHECK(a_map["bla"] == A(3,4)); CHECK(a_map.GetEntryCount() == 2); NPT_HashMap<NPT_String,A> b_map; b_map["hello"] = A(1,2); b_map["bla"] = A(3,4); CHECK(a_map == b_map); NPT_HashMap<NPT_String,A> c_map = a_map; CHECK(c_map["hello"] == a_map["hello"]); CHECK(c_map["bla"] == a_map["bla"]); CHECK(NPT_SUCCEEDED(a_map.Put("bla", A(5,6)))); CHECK(NPT_SUCCEEDED(a_map.Get("bla", a))); CHECK(*a == A(5,6)); CHECK(NPT_FAILED(a_map.Get("youyou", a))); b_map.Clear(); CHECK(b_map.GetEntryCount() == 0); a_map["youyou"] = A(6,7); CHECK(NPT_FAILED(a_map.Erase("coucou"))); CHECK(NPT_SUCCEEDED(a_map.Erase("bla"))); CHECK(!a_map.HasKey("bla")); CHECK(!(a_map == c_map)); CHECK(c_map != a_map); c_map = a_map; NPT_HashMap<NPT_String,A> d_map(c_map); CHECK(d_map == c_map); NPT_HashMap<int,int> i_map; i_map[5] = 6; i_map[6] = 7; i_map[9] = 0; CHECK(i_map[0] == 0 || i_map[0] != 0); // unknown value (will cause a valgrind warning) CHECK(i_map.GetEntryCount() == 4); NPT_HashMap<NPT_String,A> a1_map; NPT_HashMap<NPT_String,A> a2_map; a1_map["hello"] = A(1,2); a1_map["bla"] = A(2,3); a1_map["youyou"]= A(3,4); a2_map["bla"] = A(2,3); a2_map["youyou"]= A(3,4); a2_map["hello"] = A(1,2); CHECK(a1_map == a2_map); a1_map["foo"] = A(0,0); CHECK(a1_map != a2_map); a2_map["foo"] = A(0,0); CHECK(a1_map == a2_map); a2_map["foo"] = A(7,8); CHECK(a1_map != a2_map); a2_map["foo"] = A(0,0); a1_map["bir"] = A(0,0); a2_map["bar"] = A(0,0); CHECK(a1_map.GetEntryCount() == a2_map.GetEntryCount()); CHECK(a1_map != a2_map); CHECK(!(a1_map == a2_map)); NPT_HashMap<NPT_String, NPT_String> smap; for (unsigned int i=0; i<24; i++) { NPT_String s = NPT_String::Format("blabla%d", i); smap[s] = "1234"; CHECK(smap[s] == "1234"); } for (unsigned int i=0; i<24; i++) { NPT_String s = NPT_String::Format("blabla%d", i); CHECK(smap[s] == "1234"); } for (unsigned int i=0; i<24; i++) { NPT_String s = NPT_String::Format("blabla%d", i); CHECK(NPT_SUCCEEDED(smap.Erase(s))); CHECK(!smap.HasKey(s)); } CHECK(smap.GetEntryCount() == 0); Hasher hasher; NPT_HashMap<NPT_String, int, Hasher> zmap(hasher); for (unsigned int i=0; i<1024; i++) { NPT_String s = NPT_String::Format("blabla%d", i); zmap[s] = 1234; CHECK(zmap[s] == 1234); } for (unsigned int i=0; i<1024; i++) { NPT_String s = NPT_String::Format("blabla%d", i); CHECK(zmap[s] == 1234); } for (unsigned int i=0; i<1024; i++) { NPT_String s = NPT_String::Format("blabla%d", i); CHECK(NPT_SUCCEEDED(zmap.Erase(s))); CHECK(!zmap.HasKey(s)); } CHECK(zmap.GetEntryCount() == 0); NPT_HashMap<NPT_String, int> imap; for (int i=0; i<1024; i++) { NPT_String s = NPT_String::Format("blabla%d", i); imap[s] = i; CHECK(imap[s] == i); } unsigned int zz = 1024; for (NPT_HashMap<NPT_String, int>::Iterator it = imap.GetEntries(); it; ++it) { CHECK(imap.HasKey((*it).GetKey())); CHECK(imap.HasValue((*it).GetValue())); --zz; } CHECK(zz==0); NPT_HashMap<NPT_String, NPT_String*> p_map; p_map["1"] = new NPT_String("hello"); p_map["2"] = new NPT_String("good bye"); p_map.Apply(NPT_MapEntryValueDeleter<NPT_HashMap<NPT_String, NPT_String*>::Entry>()); return 0; }
static int smmap_common(caddr_t *addrp, size_t len, int prot, int flags, struct file *fp, offset_t pos) { struct vnode *vp; struct as *as = curproc->p_as; uint_t uprot, maxprot, type; int error; int in_crit = 0; if ((flags & ~(MAP_SHARED | MAP_PRIVATE | MAP_FIXED | _MAP_NEW | _MAP_LOW32 | MAP_NORESERVE | MAP_ANON | MAP_ALIGN | MAP_TEXT | MAP_INITDATA)) != 0) { /* | MAP_RENAME */ /* not implemented, let user know */ return (EINVAL); } if ((flags & MAP_TEXT) && !(prot & PROT_EXEC)) { return (EINVAL); } if ((flags & (MAP_TEXT | MAP_INITDATA)) == (MAP_TEXT | MAP_INITDATA)) { return (EINVAL); } #if defined(__sparc) /* * See if this is an "old mmap call". If so, remember this * fact and convert the flags value given to mmap to indicate * the specified address in the system call must be used. * _MAP_NEW is turned set by all new uses of mmap. */ if ((flags & _MAP_NEW) == 0) flags |= MAP_FIXED; #endif flags &= ~_MAP_NEW; type = flags & MAP_TYPE; if (type != MAP_PRIVATE && type != MAP_SHARED) return (EINVAL); if (flags & MAP_ALIGN) { if (flags & MAP_FIXED) return (EINVAL); /* alignment needs to be a power of 2 >= page size */ if (((uintptr_t)*addrp < PAGESIZE && (uintptr_t)*addrp != 0) || !ISP2((uintptr_t)*addrp)) return (EINVAL); } /* * Check for bad lengths and file position. * We let the VOP_MAP routine check for negative lengths * since on some vnode types this might be appropriate. */ if (len == 0 || (pos & (u_offset_t)PAGEOFFSET) != 0) return (EINVAL); maxprot = PROT_ALL; /* start out allowing all accesses */ uprot = prot | PROT_USER; if (fp == NULL) { ASSERT(flags & MAP_ANON); /* discard lwpchan mappings, like munmap() */ if ((flags & MAP_FIXED) && curproc->p_lcp != NULL) lwpchan_delete_mapping(curproc, *addrp, *addrp + len); as_rangelock(as); error = zmap(as, addrp, len, uprot, flags, pos); as_rangeunlock(as); /* * Tell machine specific code that lwp has mapped shared memory */ if (error == 0 && (flags & MAP_SHARED)) { /* EMPTY */ LWP_MMODEL_SHARED_AS(*addrp, len); } return (error); } else if ((flags & MAP_ANON) != 0) return (EINVAL); vp = fp->f_vnode; /* Can't execute code from "noexec" mounted filesystem. */ if ((vp->v_vfsp->vfs_flag & VFS_NOEXEC) != 0) maxprot &= ~PROT_EXEC; /* * These checks were added as part of large files. * * Return ENXIO if the initial position is negative; return EOVERFLOW * if (offset + len) would overflow the maximum allowed offset for the * type of file descriptor being used. */ if (vp->v_type == VREG) { if (pos < 0) return (ENXIO); if ((offset_t)len > (OFFSET_MAX(fp) - pos)) return (EOVERFLOW); } if (type == MAP_SHARED && (fp->f_flag & FWRITE) == 0) { /* no write access allowed */ maxprot &= ~PROT_WRITE; } /* * XXX - Do we also adjust maxprot based on protections * of the vnode? E.g. if no execute permission is given * on the vnode for the current user, maxprot probably * should disallow PROT_EXEC also? This is different * from the write access as this would be a per vnode * test as opposed to a per fd test for writability. */ /* * Verify that the specified protections are not greater than * the maximum allowable protections. Also test to make sure * that the file descriptor does allows for read access since * "write only" mappings are hard to do since normally we do * the read from the file before the page can be written. */ if (((maxprot & uprot) != uprot) || (fp->f_flag & FREAD) == 0) return (EACCES); /* * If the user specified an address, do some simple checks here */ if ((flags & MAP_FIXED) != 0) { caddr_t userlimit; /* * Use the user address. First verify that * the address to be used is page aligned. * Then make some simple bounds checks. */ if (((uintptr_t)*addrp & PAGEOFFSET) != 0) return (EINVAL); userlimit = flags & _MAP_LOW32 ? (caddr_t)USERLIMIT32 : as->a_userlimit; switch (valid_usr_range(*addrp, len, uprot, as, userlimit)) { case RANGE_OKAY: break; case RANGE_BADPROT: return (ENOTSUP); case RANGE_BADADDR: default: return (ENOMEM); } } if ((prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) && nbl_need_check(vp)) { int svmand; nbl_op_t nop; nbl_start_crit(vp, RW_READER); in_crit = 1; error = nbl_svmand(vp, fp->f_cred, &svmand); if (error != 0) goto done; if ((prot & PROT_WRITE) && (type == MAP_SHARED)) { if (prot & (PROT_READ | PROT_EXEC)) { nop = NBL_READWRITE; } else { nop = NBL_WRITE; } } else { nop = NBL_READ; } if (nbl_conflict(vp, nop, 0, LONG_MAX, svmand, NULL)) { error = EACCES; goto done; } } /* discard lwpchan mappings, like munmap() */ if ((flags & MAP_FIXED) && curproc->p_lcp != NULL) lwpchan_delete_mapping(curproc, *addrp, *addrp + len); /* * Ok, now let the vnode map routine do its thing to set things up. */ error = VOP_MAP(vp, pos, as, addrp, len, uprot, maxprot, flags, fp->f_cred, NULL); if (error == 0) { /* * Tell machine specific code that lwp has mapped shared memory */ if (flags & MAP_SHARED) { /* EMPTY */ LWP_MMODEL_SHARED_AS(*addrp, len); } if (vp->v_type == VREG && (flags & (MAP_TEXT | MAP_INITDATA)) != 0) { /* * Mark this as an executable vnode */ mutex_enter(&vp->v_lock); vp->v_flag |= VVMEXEC; mutex_exit(&vp->v_lock); } } done: if (in_crit) nbl_end_crit(vp); return (error); }